You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sw...@apache.org on 2023/01/19 06:36:25 UTC
[logging-log4cxx] 01/01: Allow use on Window Server 2016 (issue #180). Put more than the first character of thread name into the event log on Windows.
This is an automated email from the ASF dual-hosted git repository.
swebb2066 pushed a commit to branch windows_server_issue
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git
commit b47bec5ac05b60af5042a20edee0a85c16875aef
Author: Stephen Webb <st...@sabreautonomous.com.au>
AuthorDate: Thu Jan 19 17:35:37 2023 +1100
Allow use on Window Server 2016 (issue #180).
Put more than the first character of thread name into the event log on
Windows.
---
src/main/cpp/loggingevent.cpp | 32 +++++++++++++++++-----
src/main/cpp/threadutility.cpp | 25 +++++++++++++----
src/main/include/CMakeLists.txt | 7 -----
src/test/cpp/autoconfiguretestcase.cpp | 27 ++++++++++++++++++
.../resources/input/autoConfigureTest.properties | 3 +-
5 files changed, 73 insertions(+), 21 deletions(-)
diff --git a/src/main/cpp/loggingevent.cpp b/src/main/cpp/loggingevent.cpp
index daf89500..cc7f7479 100644
--- a/src/main/cpp/loggingevent.cpp
+++ b/src/main/cpp/loggingevent.cpp
@@ -374,13 +374,31 @@ const LogString& LoggingEvent::getCurrentThreadUserName()
}
log4cxx::helpers::Transcoder::decode(reinterpret_cast<const char*>(result), thread_name);
-#elif LOG4CXX_HAS_GETTHREADDESCRIPTION
- PWSTR result;
- HANDLE threadId = GetCurrentThread();
- if( GetThreadDescription( threadId, &result ) == 0 ){
- // Success
- log4cxx::helpers::Transcoder::decode(reinterpret_cast<const char*>(result), thread_name);
- LocalFree(result);
+#elif WIN32
+ typedef HRESULT (WINAPI *TGetThreadDescription)(HANDLE, PWSTR*);
+ static struct initialiser
+ {
+ HMODULE hKernelBase;
+ TGetThreadDescription GetThreadDescription;
+ initialiser()
+ : hKernelBase(GetModuleHandleA("KernelBase.dll"))
+ , GetThreadDescription(nullptr)
+ {
+ if (hKernelBase)
+ GetThreadDescription = reinterpret_cast<TGetThreadDescription>(GetProcAddress(hKernelBase, "GetThreadDescription"));
+ }
+ } win32func;
+ if (win32func.GetThreadDescription)
+ {
+ PWSTR result = 0;
+ HRESULT hr = win32func.GetThreadDescription(GetCurrentThread(), &result);
+ if (SUCCEEDED(hr))
+ {
+ std::wstring wresult = result;
+ LOG4CXX_DECODE_UNICHAR(decoded, wresult);
+ LocalFree(result);
+ thread_name = decoded;
+ }
}else{
thread_name = LOG4CXX_STR("(noname)");
}
diff --git a/src/main/cpp/threadutility.cpp b/src/main/cpp/threadutility.cpp
index 877b06ea..b579965e 100644
--- a/src/main/cpp/threadutility.cpp
+++ b/src/main/cpp/threadutility.cpp
@@ -139,13 +139,26 @@ void ThreadUtility::threadStartedNameThread(LogString threadName,
if (pthread_setname_np(static_cast<pthread_t>(nativeHandle), sthreadName.c_str()) < 0) {
LOGLOG_ERROR(LOG4CXX_STR("unable to set thread name"));
}
-#elif LOG4CXX_HAS_SETTHREADDESCRIPTION
- LOG4CXX_ENCODE_WCHAR(wthreadName, threadName);
- HRESULT hr = SetThreadDescription(static_cast<HANDLE>(nativeHandle), wthreadName.c_str());
- if(FAILED(hr)){
- LOGLOG_ERROR( LOG4CXX_STR("unable to set thread name") );
+#elif WIN32
+ typedef HRESULT (WINAPI *TSetThreadDescription)(HANDLE, PCWSTR);
+ static struct initialiser
+ {
+ HMODULE hKernelBase;
+ TSetThreadDescription SetThreadDescription;
+ initialiser()
+ : hKernelBase(GetModuleHandleA("KernelBase.dll"))
+ , SetThreadDescription(nullptr)
+ {
+ if (hKernelBase)
+ SetThreadDescription = reinterpret_cast<TSetThreadDescription>(GetProcAddress(hKernelBase, "SetThreadDescription"));
+ }
+ } win32Func;
+ if (win32Func.SetThreadDescription)
+ {
+ LOG4CXX_ENCODE_WCHAR(wthreadName, threadName);
+ if(FAILED(win32Func.SetThreadDescription(static_cast<HANDLE>(nativeHandle), wthreadName.c_str())))
+ LOGLOG_ERROR( LOG4CXX_STR("unable to set thread name") );
}
-
#endif
}
diff --git a/src/main/include/CMakeLists.txt b/src/main/include/CMakeLists.txt
index 59982cf3..62f61bd4 100644
--- a/src/main/include/CMakeLists.txt
+++ b/src/main/include/CMakeLists.txt
@@ -146,11 +146,6 @@ if(UNIX)
endif()
endif(UNIX)
-if(WIN32)
- CHECK_SYMBOL_EXISTS(SetThreadDescription "windows.h;processthreadsapi.h" HAS_SETTHREADDESCRIPTION)
- CHECK_SYMBOL_EXISTS(GetThreadDescription "windows.h;processthreadsapi.h" HAS_GETTHREADDESCRIPTION)
-endif(WIN32)
-
foreach(varName
HAS_THREAD_LOCAL
HAS_STD_LOCALE
@@ -163,8 +158,6 @@ foreach(varName
HAS_PTHREAD_SIGMASK
HAS_PTHREAD_SETNAME
HAS_PTHREAD_GETNAME
- HAS_SETTHREADDESCRIPTION
- HAS_GETTHREADDESCRIPTION
)
if(${varName} EQUAL 0)
continue()
diff --git a/src/test/cpp/autoconfiguretestcase.cpp b/src/test/cpp/autoconfiguretestcase.cpp
index e486727e..73527e73 100644
--- a/src/test/cpp/autoconfiguretestcase.cpp
+++ b/src/test/cpp/autoconfiguretestcase.cpp
@@ -24,6 +24,7 @@
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/pool.h>
#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/threadutility.h>
#include <thread>
#include <apr_file_io.h>
#include <apr_file_info.h>
@@ -104,11 +105,37 @@ public:
LOGUNIT_ASSERT(rep->isConfigured());
}
+ // Base for a template that identifies whather std::thread::id has a native_handle member
+ template< class, class = void >
+ struct has_native_handle_member : std::false_type { };
+
+ template< class T >
+ struct has_native_handle_member<T,
+ std::void_t<decltype(std::declval<T&>().native_handle)>
+ > : std::true_type { };
+
+ template <typename V>
+ void setThreadName(const V& n, const LogString& name,
+ typename std::enable_if<!has_native_handle_member<V>::value, bool>::type* tag = 0)
+ {
+#ifdef WIN32
+ log4cxx::helpers::ThreadUtility::instance()->threadStartedNameThread(name, n, ::GetCurrentThread());
+#endif
+ }
+ template <typename V>
+ void setThreadName(const V& n, const LogString& name,
+ typename std::enable_if<has_native_handle_member<V>::value, bool>::type* tag = 0)
+ {
+ log4cxx::helpers::ThreadUtility::instance()->threadStartedNameThread(name, n, n.native_handle())
+ }
+
void test2()
{
+ setThreadName(std::this_thread::get_id(), LOG4CXX_STR("main"));
auto debugLogger = LogManager::getLogger(LOG4CXX_STR("AutoConfig.test2"));
LOGUNIT_ASSERT(debugLogger);
LOGUNIT_ASSERT(debugLogger->isDebugEnabled());
+ LOG4CXX_DEBUG(debugLogger, "Test message");
}
void test3()
diff --git a/src/test/resources/input/autoConfigureTest.properties b/src/test/resources/input/autoConfigureTest.properties
index 1187d130..604f878f 100644
--- a/src/test/resources/input/autoConfigureTest.properties
+++ b/src/test/resources/input/autoConfigureTest.properties
@@ -14,12 +14,13 @@
# limitations under the License.
#
log4j.rootCategory=INFO, A1
+log4j.threadConfiguration=NameThreadOnly
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.File=output/autoConfigureTest.log
log4j.appender.A1.Append=false
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-log4j.appender.A1.layout.ConversionPattern=%m%n
+log4j.appender.A1.layout.ConversionPattern=%T %m%n
#log4j.logger.AutoConfig.test1=DEBUG
log4j.logger.AutoConfig.test2=DEBUG