From 7a70b74a814b67aec643d5e859907d3776756167 Mon Sep 17 00:00:00 2001 From: Olivier Smeesters Date: Tue, 29 Jun 2021 13:52:57 +0200 Subject: [PATCH 1/2] Add NativeThreadInfo + use in Message + test with PatternFormatter --- Foundation/include/Poco/NativeThreadInfo.h | 70 +++++++++++++++ .../include/Poco/NativeThreadInfo_POSIX.h | 51 +++++++++++ Foundation/include/Poco/NativeThreadInfo_VX.h | 46 ++++++++++ .../include/Poco/NativeThreadInfo_WIN32.h | 46 ++++++++++ .../include/Poco/NativeThreadInfo_WINCE.h | 46 ++++++++++ Foundation/src/Message.cpp | 6 ++ Foundation/src/NativeThreadInfo.cpp | 40 +++++++++ Foundation/src/NativeThreadInfo_POSIX.cpp | 53 +++++++++++ Foundation/src/NativeThreadInfo_VX.cpp | 39 ++++++++ Foundation/src/NativeThreadInfo_WIN32.cpp | 74 +++++++++++++++ Foundation/src/NativeThreadInfo_WINCE.cpp | 40 +++++++++ Foundation/testsuite/src/LoggerTest.cpp | 90 ++++++++++++++++++- 12 files changed, 599 insertions(+), 2 deletions(-) create mode 100644 Foundation/include/Poco/NativeThreadInfo.h create mode 100644 Foundation/include/Poco/NativeThreadInfo_POSIX.h create mode 100644 Foundation/include/Poco/NativeThreadInfo_VX.h create mode 100644 Foundation/include/Poco/NativeThreadInfo_WIN32.h create mode 100644 Foundation/include/Poco/NativeThreadInfo_WINCE.h create mode 100644 Foundation/src/NativeThreadInfo.cpp create mode 100644 Foundation/src/NativeThreadInfo_POSIX.cpp create mode 100644 Foundation/src/NativeThreadInfo_VX.cpp create mode 100644 Foundation/src/NativeThreadInfo_WIN32.cpp create mode 100644 Foundation/src/NativeThreadInfo_WINCE.cpp diff --git a/Foundation/include/Poco/NativeThreadInfo.h b/Foundation/include/Poco/NativeThreadInfo.h new file mode 100644 index 0000000000..d6e062af0f --- /dev/null +++ b/Foundation/include/Poco/NativeThreadInfo.h @@ -0,0 +1,70 @@ +// +// NativeThreadInfo.h +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfo +// +// Definition of the NativeThreadInfo class. +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Foundation_NativeThreadInfo_INCLUDED +#define Foundation_NativeThreadInfo_INCLUDED + +#include "Poco/Foundation.h" + +#if defined(POCO_OS_FAMILY_WINDOWS) +#if defined(_WIN32_WCE) +#include "Poco/NativeThreadInfo_WINCE.h" +#else +#include "Poco/NativeThreadInfo_WIN32.h" +#endif +#elif defined(POCO_VXWORKS) +#include "Poco/NativeThreadInfo_VX.h" +#else +#include "Poco/NativeThreadInfo_POSIX.h" +#endif + +namespace Poco { + +class Foundation_API NativeThreadInfo: private NativeThreadInfoImpl + /// This class implements a platform independent API to query information about a native thread. +{ +public: + typedef NativeThreadInfoImpl::ThreadIdImpl ThreadId; + typedef NativeThreadInfoImpl::HandleImpl Handle; + + NativeThreadInfo(); + /// Creates a thread info for the current thread. + + NativeThreadInfo(Handle handle); + /// Creates a thread info for a specific thread id. + + std::string name() const; + /// Returns the name of the thread. + + ThreadId id() const; +}; + +// +// inlines +// +inline std::string NativeThreadInfo::name() const +{ + return nameImpl(); +} + +inline NativeThreadInfo::ThreadId NativeThreadInfo::id() const +{ + return idImpl(); +} + +} // namespace Poco + +#endif // Foundation_NativeThreadInfo_INCLUDED diff --git a/Foundation/include/Poco/NativeThreadInfo_POSIX.h b/Foundation/include/Poco/NativeThreadInfo_POSIX.h new file mode 100644 index 0000000000..4608ff9d4b --- /dev/null +++ b/Foundation/include/Poco/NativeThreadInfo_POSIX.h @@ -0,0 +1,51 @@ +// +// NativeThreadInfo_POSIX.h +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfo +// +// Definition of the NativeThreadInfoImpl class for POSIX NativeThreadInfos. +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Foundation_NativeThreadInfo_POSIX_INCLUDED +#define Foundation_NativeThreadInfo_POSIX_INCLUDED + + +#include "Poco/Foundation.h" +#include +#include +#include + +namespace Poco { + +class Foundation_API NativeThreadInfoImpl +{ +public: +#if (POCO_OS == POCO_OS_MAC_OS_X) + typedef uint64_t ThreadIdImpl; +#else + typedef pid_t ThreadIdImpl; +#endif + typedef pthread_t HandleImpl; + + NativeThreadInfoImpl(HandleImpl handle); + + std::string nameImpl() const; + ThreadIdImpl idImpl() const; + + static HandleImpl currentThreadHandleImpl(); + +private: + HandleImpl _thread; +}; + +} // namespace Poco + +#endif // Foundation_NativeThreadInfo_POSIX_INCLUDED diff --git a/Foundation/include/Poco/NativeThreadInfo_VX.h b/Foundation/include/Poco/NativeThreadInfo_VX.h new file mode 100644 index 0000000000..7fad197249 --- /dev/null +++ b/Foundation/include/Poco/NativeThreadInfo_VX.h @@ -0,0 +1,46 @@ +// +// NativeThreadInfo_VX.h +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfo +// +// Definition of the NativeThreadInfoImpl class for VX NativeThreadInfos. +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Foundation_NativeThreadInfo_VX_INCLUDED +#define Foundation_NativeThreadInfo_VX_INCLUDED + + +#include "Poco/Foundation.h" +#include +#include + +namespace Poco { + +class Foundation_API NativeThreadInfoImpl +{ +public: + typedef int ThreadIdImpl; + typedef int HandleImpl; + + NativeThreadInfoImpl(HandleImpl handle); + + std::string nameImpl() const; + ThreadIdImpl idImpl() const; + + static HandleImpl currentThreadHandleImpl(); + +private: + HandleImpl _thread; +}; + +} // namespace Poco + +#endif // Foundation_NativeThreadInfo_VX_INCLUDED diff --git a/Foundation/include/Poco/NativeThreadInfo_WIN32.h b/Foundation/include/Poco/NativeThreadInfo_WIN32.h new file mode 100644 index 0000000000..90eb417598 --- /dev/null +++ b/Foundation/include/Poco/NativeThreadInfo_WIN32.h @@ -0,0 +1,46 @@ +// +// NativeThreadInfo_WIN32.h +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfo +// +// Definition of the NativeThreadInfoImpl class for WIN32 NativeThreadInfos. +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Foundation_NativeThreadInfo_WIN32_INCLUDED +#define Foundation_NativeThreadInfo_WIN32_INCLUDED + + +#include "Poco/Foundation.h" +#include +#include "Poco/UnWindows.h" + +namespace Poco { + +class Foundation_API NativeThreadInfoImpl +{ +public: + typedef DWORD ThreadIdImpl; + typedef HANDLE HandleImpl; + + NativeThreadInfoImpl(HandleImpl handle); + + std::string nameImpl() const; + ThreadIdImpl idImpl() const; + + static HandleImpl currentThreadHandleImpl(); + +private: + HandleImpl _thread; +}; + +} // namespace Poco + +#endif // Foundation_NativeThreadInfo_WIN32_INCLUDED diff --git a/Foundation/include/Poco/NativeThreadInfo_WINCE.h b/Foundation/include/Poco/NativeThreadInfo_WINCE.h new file mode 100644 index 0000000000..388f46402b --- /dev/null +++ b/Foundation/include/Poco/NativeThreadInfo_WINCE.h @@ -0,0 +1,46 @@ +// +// NativeThreadInfo_WINCE.h +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfo +// +// Definition of the NativeThreadInfoImpl class for WINCE NativeThreadInfos. +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#ifndef Foundation_NativeThreadInfo_WINCE_INCLUDED +#define Foundation_NativeThreadInfo_WINCE_INCLUDED + + +#include "Poco/Foundation.h" +#include +#include "Poco/UnWindows.h" + +namespace Poco { + +class Foundation_API NativeThreadInfoImpl +{ +public: + typedef DWORD ThreadIdImpl; + typedef DWORD HandleImpl; + + NativeThreadInfoImpl(HandleImpl handle); + + std::string nameImpl() const; + ThreadIdImpl idImpl() const; + + static HandleImpl currentThreadHandleImpl(); + +private: + HandleImpl _thread; +}; + +} // namespace Poco + +#endif // Foundation_NativeThreadInfo_WINCE_INCLUDED diff --git a/Foundation/src/Message.cpp b/Foundation/src/Message.cpp index 94a3b53b3c..1b6267ab64 100644 --- a/Foundation/src/Message.cpp +++ b/Foundation/src/Message.cpp @@ -18,6 +18,7 @@ #include "Poco/Process.h" #endif #include "Poco/Thread.h" +#include "Poco/NativeThreadInfo.h" #include @@ -133,6 +134,11 @@ void Message::init() _tid = pThread->id(); _thread = pThread->name(); } + else { + NativeThreadInfo info; + _tid = info.id(); + _thread = info.name(); + } } diff --git a/Foundation/src/NativeThreadInfo.cpp b/Foundation/src/NativeThreadInfo.cpp new file mode 100644 index 0000000000..f45798609b --- /dev/null +++ b/Foundation/src/NativeThreadInfo.cpp @@ -0,0 +1,40 @@ +// +// NativeThreadInfo.cpp +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfo +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/NativeThreadInfo.h" + +#if defined(POCO_OS_FAMILY_WINDOWS) +#if defined(_WIN32_WCE) +#include "NativeThreadInfo_WINCE.cpp" +#else +#include "NativeThreadInfo_WIN32.cpp" +#endif +#elif defined(POCO_VXWORKS) +#include "NativeThreadInfo_VX.cpp" +#else +#include "NativeThreadInfo_POSIX.cpp" +#endif + + +namespace Poco { + +NativeThreadInfo::NativeThreadInfo(Handle handle): + NativeThreadInfoImpl{handle} +{ } + +NativeThreadInfo::NativeThreadInfo(): + NativeThreadInfo{ NativeThreadInfoImpl::currentThreadHandleImpl() } +{ } + +} // namespace Poco diff --git a/Foundation/src/NativeThreadInfo_POSIX.cpp b/Foundation/src/NativeThreadInfo_POSIX.cpp new file mode 100644 index 0000000000..a5fe6c8e18 --- /dev/null +++ b/Foundation/src/NativeThreadInfo_POSIX.cpp @@ -0,0 +1,53 @@ +// +// NativeThreadInfo_POSIX.cpp +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfoImpl +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/NativeThreadInfo_POSIX.h" +#include +#include + +namespace Poco { + +NativeThreadInfoImpl::NativeThreadInfoImpl(NativeThreadInfoImpl::HandleImpl handle): + _thread(handle) +{ +} + +std::string NativeThreadInfoImpl::nameImpl() const +{ + std::string result(128, '\0'); + int rc = pthread_getname_np(_thread, &result[0], result.size()); + if (rc < 0) { + return {}; + } + result.resize(std::strlen(result.data())); + return result; +} + +NativeThreadInfoImpl::ThreadIdImpl NativeThreadInfoImpl::idImpl() const +{ + ThreadIdImpl tid; +#if (POCO_OS == POCO_OS_MAC_OS_X) + pthread_threadid_np(_thread, &tid); +#else + tid = gettid(); +#endif + return tid; +} + +NativeThreadInfoImpl::HandleImpl NativeThreadInfoImpl::currentThreadHandleImpl() +{ + return pthread_self(); +} + +} // namespace Poco diff --git a/Foundation/src/NativeThreadInfo_VX.cpp b/Foundation/src/NativeThreadInfo_VX.cpp new file mode 100644 index 0000000000..2393ddfa2b --- /dev/null +++ b/Foundation/src/NativeThreadInfo_VX.cpp @@ -0,0 +1,39 @@ +// +// NativeThreadInfo_VX.cpp +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfoImpl +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/NativeThreadInfo_VX.h" + +namespace Poco { + +NativeThreadInfoImpl::NativeThreadInfoImpl(NativeThreadInfoImpl::HandleImpl handle): + _thread(handle) +{ +} + +std::string NativeThreadInfoImpl::nameImpl() const +{ + return taskName(_thread); +} + +pid_t NativeThreadInfoImpl::idImpl() const +{ + return _thread; +} + +NativeThreadInfoImpl::HandleImpl NativeThreadInfoImpl::currentThreadHandleImpl() +{ + return taskIdSelf(); +} + +} // namespace Poco diff --git a/Foundation/src/NativeThreadInfo_WIN32.cpp b/Foundation/src/NativeThreadInfo_WIN32.cpp new file mode 100644 index 0000000000..d03b6c6168 --- /dev/null +++ b/Foundation/src/NativeThreadInfo_WIN32.cpp @@ -0,0 +1,74 @@ +// +// NativeThreadInfo_WIN32.cpp +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfoImpl +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/NativeThreadInfo_WIN32.h" +#include +#include + +namespace Poco { + +NativeThreadInfoImpl::NativeThreadInfoImpl(NativeThreadInfoImpl::HandleImpl handle): + _thread(handle) +{ +} + +std::string NativeThreadInfoImpl::nameImpl() const +{ + HRESULT hr = GetThreadDescription(_thread, &data); + if (SUCCEEDED(hr)) + { + std::string result; + const UINT codePage = CP_THREAD_ACP; + const DWORD flags = 0; + int convSize = WideCharToMultiByte( + codePage, + flags, + data, + -1, + NULL /* LPSTR lpMultiByteStr*/, + 0 /* int cbMultiByte */, + NULL /* LPCCH lpDefaultChar */, + NULL /* LPBOOL lpUsedDefaultChar */ + ); + if (convSize >= 0) { + result.resize(convSize); + WideCharToMultiByte( + codePage, + flags, + data, + -1, + &result[0], + convSize, + NULL /* LPCCH lpDefaultChar */, + NULL /* LPBOOL lpUsedDefaultChar */ + ); + } + LocalFree(data); + return result; + } + + return {}; +} + +NativeThreadInfoImpl::ThreadIdImpl NativeThreadInfoImpl::idImpl() const +{ + return GetThreadId(_thread); +} + +NativeThreadInfoImpl::HandleImpl NativeThreadInfoImpl::currentThreadHandleImpl() +{ + return GetCurrentThread(); +} + +} // namespace Poco diff --git a/Foundation/src/NativeThreadInfo_WINCE.cpp b/Foundation/src/NativeThreadInfo_WINCE.cpp new file mode 100644 index 0000000000..c7725d5ed2 --- /dev/null +++ b/Foundation/src/NativeThreadInfo_WINCE.cpp @@ -0,0 +1,40 @@ +// +// NativeThreadInfo_WINCE.cpp +// +// Library: Foundation +// Package: Threading +// Module: NativeThreadInfoImpl +// +// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/NativeThreadInfo_WINCE.h" +#include + +namespace Poco { + +NativeThreadInfoImpl::NativeThreadInfoImpl(NativeThreadInfoImpl::HandleImpl handle): + _thread(handle) +{ +} + +std::string NativeThreadInfoImpl::nameImpl() const +{ + return {}; +} + +NativeThreadInfoImpl::ThreadIdImpl NativeThreadInfoImpl::idImpl() const +{ + return _thread; +} + +NativeThreadInfoImpl::HandleImpl NativeThreadInfoImpl::currentThreadHandleImpl() +{ + return GetCurrentThreadId(); +} + +} // namespace Poco diff --git a/Foundation/testsuite/src/LoggerTest.cpp b/Foundation/testsuite/src/LoggerTest.cpp index cf6ba65632..d56a72ecc4 100644 --- a/Foundation/testsuite/src/LoggerTest.cpp +++ b/Foundation/testsuite/src/LoggerTest.cpp @@ -14,13 +14,22 @@ #include "Poco/Logger.h" #include "Poco/AutoPtr.h" #include "TestChannel.h" - +#include "Poco/Thread.h" +#include "Poco/Event.h" +#include "Poco/PatternFormatter.h" +#include "Poco/FormattingChannel.h" +#include +#include +#include using Poco::Logger; using Poco::Channel; using Poco::Message; using Poco::AutoPtr; - +using Poco::PatternFormatter; +using Poco::FormattingChannel; +using Poco::Event; +using Poco::Thread; LoggerTest::LoggerTest(const std::string& name): CppUnit::TestCase(name) { @@ -289,6 +298,81 @@ void LoggerTest::testDump() pChannel->clear(); } +namespace ThreadNameTestStrings { +const std::string loggerName = "Logger"; +const std::string threadName = "ThreadName"; +const std::string message = "Test message"; +} + +template +std::string LoggerTest::doTestFormatThreadName(ThreadFactory makeThread) +{ + AutoPtr pChannel = new TestChannel; + AutoPtr fmt = new PatternFormatter("%s:%I:%T:%q:%t"); + AutoPtr pFmtChannel = new FormattingChannel(fmt, pChannel); + + Logger& logger = Logger::get(ThreadNameTestStrings::loggerName); + logger.setChannel(pFmtChannel); + logger.setLevel(Message::PRIO_INFORMATION); + + Event ev; + auto thr = makeThread( + ThreadNameTestStrings::threadName, + [&ev, &logger] { + logger.information(ThreadNameTestStrings::message); + ev.set(); + }); + ev.wait(); + + thr->join(); + + const std::string logMsg = pChannel->getLastMessage().getText(); + std::vector parts; + std::size_t p = 0; + while (p != std::string::npos && p < logMsg.size()) { + auto q = logMsg.find(':', p); + if (q == logMsg.npos) { + q = logMsg.size(); + } + parts.push_back(logMsg.substr(p, q-p)); + p = q + 1; + } + assertEqual( ThreadNameTestStrings::loggerName, parts[0] ); + assertEqual( ThreadNameTestStrings::threadName, parts[2] ); + assertEqual( "I", parts[3] ); + assertEqual( ThreadNameTestStrings::message, parts[4] ); + + return parts[1]; +} + +void LoggerTest::testFormatThreadName() +{ + auto tidStr = doTestFormatThreadName( + [](std::string name, auto body) { + auto thr = std::make_unique(name); + thr->startFunc(std::move(body)); + return std::move(thr); + } + ); + assertEqual( "1", tidStr ); +} + +void LoggerTest::testFormatStdThreadName() +{ +#ifdef POCO_OS_FAMILY_UNIX + doTestFormatThreadName( + [](std::string name, auto bodyIn) { + auto thr = std::make_unique( + [name, body = std::move(bodyIn)] { + pthread_setname_np(pthread_self(), name.c_str()); + body(); + } + ); + return std::move(thr); + } + ); +#endif +} void LoggerTest::setUp() { @@ -309,6 +393,8 @@ CppUnit::Test* LoggerTest::suite() CppUnit_addTest(pSuite, LoggerTest, testFormat); CppUnit_addTest(pSuite, LoggerTest, testFormatAny); CppUnit_addTest(pSuite, LoggerTest, testDump); + CppUnit_addTest(pSuite, LoggerTest, testFormatThreadName); + CppUnit_addTest(pSuite, LoggerTest, testFormatStdThreadName); return pSuite; } From b400b027f066cdef16264c20d6ec0e1584fc8ce7 Mon Sep 17 00:00:00 2001 From: Olivier Smeesters Date: Tue, 6 Jul 2021 17:09:47 +0200 Subject: [PATCH 2/2] Fix NativeThreadInfo for glibc without gettid --- Foundation/src/NativeThreadInfo_POSIX.cpp | 10 ++++++++++ Foundation/testsuite/src/LoggerTest.h | 6 +++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Foundation/src/NativeThreadInfo_POSIX.cpp b/Foundation/src/NativeThreadInfo_POSIX.cpp index a5fe6c8e18..2def591140 100644 --- a/Foundation/src/NativeThreadInfo_POSIX.cpp +++ b/Foundation/src/NativeThreadInfo_POSIX.cpp @@ -15,6 +15,16 @@ #include "Poco/NativeThreadInfo_POSIX.h" #include #include +#include + +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 +#include +#ifdef SYS_gettid +#define gettid() syscall(SYS_gettid) +#else +#define gettid() (0) +#endif +#endif namespace Poco { diff --git a/Foundation/testsuite/src/LoggerTest.h b/Foundation/testsuite/src/LoggerTest.h index 39fab3da8d..209aa083b9 100644 --- a/Foundation/testsuite/src/LoggerTest.h +++ b/Foundation/testsuite/src/LoggerTest.h @@ -16,7 +16,7 @@ #include "Poco/Foundation.h" #include "CppUnit/TestCase.h" - +#include class LoggerTest: public CppUnit::TestCase { @@ -28,6 +28,8 @@ class LoggerTest: public CppUnit::TestCase void testFormat(); void testFormatAny(); void testDump(); + void testFormatThreadName(); + void testFormatStdThreadName(); void setUp(); void tearDown(); @@ -35,6 +37,8 @@ class LoggerTest: public CppUnit::TestCase static CppUnit::Test* suite(); private: + template + std::string doTestFormatThreadName(ThreadFactory makeThread); };