set thread name (#3664)

* set thread name

* fix dead lock

* fix code style & return fake name

* fix code style

* fix code style

Co-authored-by: Aleksandar Fabijanic <aleks-f@users.noreply.github.com>
This commit is contained in:
JackyWoo 2022-07-18 18:21:33 +08:00 committed by GitHub
parent 2a36359bc7
commit 1d28d2d42d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 240 additions and 60 deletions

View File

@ -52,6 +52,11 @@
#define POCO_THREAD_STACK_SIZE 0
#endif
// Defined to desired max thread name length
#ifndef POCO_MAX_THREAD_NAME_LEN
#define POCO_MAX_THREAD_NAME_LEN 15
#endif
// Define to override system-provided
// minimum thread priority value on POSIX

View File

@ -95,6 +95,7 @@ public:
void setName(const std::string& name);
/// Sets the name of the thread.
/// Note that it only take effect before start method invoked.
void setPriority(Priority prio);
/// Sets the thread's priority.
@ -275,10 +276,8 @@ private:
Thread& operator = (const Thread&);
int _id;
std::string _name;
ThreadLocalStorage* _pTLS;
Event _event;
mutable FastMutex _mutex;
friend class ThreadLocalStorage;
friend class PooledThread;
@ -302,17 +301,13 @@ inline int Thread::id() const
inline std::string Thread::name() const
{
FastMutex::ScopedLock lock(_mutex);
return _name;
return getNameImpl();
}
inline std::string Thread::getName() const
{
FastMutex::ScopedLock lock(_mutex);
return _name;
return getNameImpl();
}

View File

@ -36,10 +36,8 @@
#include <cstring>
#endif
namespace Poco {
class Foundation_API ThreadImpl
{
public:
@ -64,6 +62,12 @@ public:
~ThreadImpl();
TIDImpl tidImpl() const;
void setNameImpl(const std::string& threadName);
std::string getNameImpl() const;
std::string getOSThreadNameImpl();
/// Returns the thread's name, expressed as an operating system
/// specific name value. Return empty string if thread is not running.
/// For test used only.
void setPriorityImpl(int prio);
int getPriorityImpl() const;
void setOSPriorityImpl(int prio, int policy = SCHED_OTHER);
@ -141,6 +145,7 @@ private:
std::size_t stackSize;
bool started;
bool joined;
std::string name;
mutable FastMutex mutex;
};

View File

@ -70,6 +70,12 @@ public:
~ThreadImpl();
TIDImpl tidImpl() const;
void setNameImpl(const std::string& threadName);
std::string getNameImpl() const;
std::string getOSThreadNameImpl();
/// Returns the thread's name, expressed as an operating system
/// specific name value. Return empty string if thread is not running.
/// For test used only.
void setPriorityImpl(int prio);
int getPriorityImpl() const;
void setOSPriorityImpl(int prio, int policy = 0);
@ -111,11 +117,12 @@ protected:
Runnable* pRunnableTarget;
AutoPtr<CallbackData> pCallbackTarget;
int task;
int prio;
int osPrio;
Event done;
int stackSize;
int task;
int prio;
int osPrio;
Event done;
int stackSize;
std::string name;
};
private:

View File

@ -57,6 +57,12 @@ public:
~ThreadImpl();
TIDImpl tidImpl() const;
void setNameImpl(const std::string& threadName);
std::string getNameImpl() const;
std::string getOSThreadNameImpl();
/// Returns the thread's name, expressed as an operating system
/// specific name value. Return empty string if thread is not running.
/// For test used only.
void setPriorityImpl(int prio);
int getPriorityImpl() const;
void setOSPriorityImpl(int prio, int policy = 0);
@ -116,6 +122,7 @@ private:
DWORD _threadId;
int _prio;
int _stackSize;
std::string _name;
static CurrentThreadHolder _currentThreadHolder;
};

View File

@ -57,6 +57,12 @@ public:
~ThreadImpl();
TIDImpl tidImpl() const;
void setNameImpl(const std::string& threadName);
std::string getNameImpl() const;
std::string getOSThreadNameImpl();
/// Returns the thread's name, expressed as an operating system
/// specific name value. Return empty string if thread is not running.
/// For test used only.
void setPriorityImpl(int prio);
int getPriorityImpl() const;
void setOSPriorityImpl(int prio, int policy = 0);
@ -112,6 +118,7 @@ private:
DWORD _threadId;
int _prio;
int _stackSize;
std::string _name;
static CurrentThreadHolder _currentThreadHolder;
};

View File

@ -90,19 +90,19 @@ private:
Thread::Thread():
_id(uniqueId()),
_name(makeName()),
_pTLS(0),
_event(true)
{
setNameImpl(makeName());
}
Thread::Thread(const std::string& name):
_id(uniqueId()),
_name(name),
_pTLS(0),
_event(true)
{
setNameImpl(name);
}
@ -210,9 +210,7 @@ int Thread::uniqueId()
void Thread::setName(const std::string& name)
{
FastMutex::ScopedLock lock(_mutex);
_name = name;
setNameImpl(name);
}

View File

@ -62,21 +62,25 @@ namespace
#endif
namespace {
void setThreadName(pthread_t thread, const std::string& threadName)
namespace
{
#if (POCO_OS == POCO_OS_MAC_OS_X)
pthread_setname_np(threadName.c_str()); // __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2)
#else
if (pthread_setname_np(thread, threadName.c_str()) == ERANGE && threadName.size() > 15)
void setThreadName(const std::string& threadName)
{
std::string truncName(threadName, 0, 7);
truncName.append("~");
truncName.append(threadName, threadName.size() - 7, 7);
pthread_setname_np(thread, truncName.c_str());
}
#if (POCO_OS == POCO_OS_MAC_OS_X)
if (pthread_setname_np(threadName.c_str()))
#else
if (pthread_setname_np(pthread_self(), threadName.c_str()))
#endif
}
throw Poco::SystemException("cannot get thread name");
}
std::string getThreadName()
{
char name[POCO_MAX_THREAD_NAME_LEN + 1]{'\0'};
if (pthread_getname_np(pthread_self(), name, POCO_MAX_THREAD_NAME_LEN + 1))
throw Poco::SystemException("cannot get thread name");
return name;
}
}
@ -100,6 +104,44 @@ ThreadImpl::~ThreadImpl()
}
}
void ThreadImpl::setNameImpl(const std::string& threadName)
{
std::string realName = threadName;
#if (POCO_OS == POCO_OS_MAC_OS_X)
if (threadName.size() > POCO_MAX_THREAD_NAME_LEN)
{
int half = (POCO_MAX_THREAD_NAME_LEN - 1) / 2;
#else
if (threadName.size() > std::min(POCO_MAX_THREAD_NAME_LEN, 15))
{
int half = (std::min(POCO_MAX_THREAD_NAME_LEN, 15) - 1) / 2;
#endif
std::string truncName(threadName, 0, half);
truncName.append("~");
truncName.append(threadName, threadName.size() - half);
realName = truncName;
}
ScopedLock<FastMutex> lock(_pData->mutex);
if (realName != _pData->name)
{
_pData->name = realName;
}
}
std::string ThreadImpl::getNameImpl() const
{
ScopedLock<FastMutex> lock(_pData->mutex);
return _pData->name;
}
std::string ThreadImpl::getOSThreadNameImpl()
{
return isRunningImpl() ? getThreadName() : "";
}
void ThreadImpl::setPriorityImpl(int prio)
{
@ -350,9 +392,14 @@ void* ThreadImpl::runnableEntry(void* pThread)
pthread_sigmask(SIG_BLOCK, &sset, 0);
#endif
ThreadImpl* pThreadImpl = reinterpret_cast<ThreadImpl*>(pThread);
setThreadName(pThreadImpl->_pData->thread, reinterpret_cast<Thread*>(pThread)->getName());
auto* pThreadImpl = reinterpret_cast<ThreadImpl*>(pThread);
AutoPtr<ThreadData> pData = pThreadImpl->_pData;
{
FastMutex::ScopedLock lock(pData->mutex);
setThreadName(pData->name);
}
try
{
pData->pRunnableTarget->run();

View File

@ -37,6 +37,38 @@ ThreadImpl::~ThreadImpl()
}
void ThreadImpl::setNameImpl(const std::string& threadName)
{
std::string realName = threadName;
if (threadName.size() > POCO_MAX_THREAD_NAME_LEN)
{
int half = (POCO_MAX_THREAD_NAME_LEN - 1) / 2;
std::string truncName(threadName, 0, half);
truncName.append("~");
truncName.append(threadName, threadName.size() - half);
realName = truncName;
}
if (realName != _pData->name)
{
_pData->name = realName;
}
}
std::string ThreadImpl::getNameImpl() const
{
return _pData->name;
}
std::string ThreadImpl::getOSThreadNameImpl()
{
// return fake thread name;
return isRunningImpl() ? _pData->name : "";
}
void ThreadImpl::setPriorityImpl(int prio)
{
if (prio != _pData->prio)
@ -141,7 +173,7 @@ ThreadImpl* ThreadImpl::currentImpl()
ThreadImpl::TIDImpl ThreadImpl::currentTidImpl()
{
return taskIdSelf();
return taskIdSelf();
}
long ThreadImpl::currentOsTidImpl()
@ -181,6 +213,7 @@ void ThreadImpl::runnableEntry(void* pThread, int, int, int, int, int, int, int,
_pCurrent = reinterpret_cast<ThreadImpl*>(pThread);
AutoPtr<ThreadData> pData = _pCurrent->_pData;
try
{
pData->pRunnableTarget->run();

View File

@ -18,9 +18,6 @@
#include <process.h>
#if defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)
namespace
{
/// See <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>
@ -38,29 +35,26 @@ namespace
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
void setThreadName(DWORD dwThreadID, const char* threadName)
void setThreadName(DWORD dwThreadID, const std::string& threadName)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName.c_str();
info.dwThreadID = dwThreadID;
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
}
__except (EXCEPTION_CONTINUE_EXECUTION)
{
}
}
}
#endif
namespace Poco {
@ -82,6 +76,37 @@ ThreadImpl::~ThreadImpl()
}
void ThreadImpl::setNameImpl(const std::string& threadName)
{
std::string realName = threadName;
if (threadName.size() > POCO_MAX_THREAD_NAME_LEN)
{
int half = (POCO_MAX_THREAD_NAME_LEN - 1) / 2;
std::string truncName(threadName, 0, half);
truncName.append("~");
truncName.append(threadName, threadName.size() - half);
realName = truncName;
}
if (realName != _name)
{
_name = realName;
}
}
std::string ThreadImpl::getNameImpl() const
{
return _name;
}
std::string ThreadImpl::getOSThreadNameImpl()
{
// return fake thread name
return isRunningImpl() ? _name : "";
}
void ThreadImpl::setPriorityImpl(int prio)
{
if (prio != _prio)
@ -200,10 +225,9 @@ DWORD WINAPI ThreadImpl::runnableEntry(LPVOID pThread)
unsigned __stdcall ThreadImpl::runnableEntry(void* pThread)
#endif
{
_currentThreadHolder.set(reinterpret_cast<ThreadImpl*>(pThread));
#if defined(POCO_WIN32_DEBUGGER_THREAD_NAMES)
setThreadName(-1, reinterpret_cast<Thread*>(pThread)->getName().c_str());
#endif
auto * pThreadImpl = reinterpret_cast<ThreadImpl*>(pThread);
_currentThreadHolder.set(pThreadImpl);
setThreadName(-1, pThreadImpl->_name);
try
{
reinterpret_cast<ThreadImpl*>(pThread)->_pRunnableTarget->run();

View File

@ -16,7 +16,6 @@
#include "Poco/Exception.h"
#include "Poco/ErrorHandler.h"
namespace Poco {
@ -38,6 +37,35 @@ ThreadImpl::~ThreadImpl()
if (_thread) CloseHandle(_thread);
}
void ThreadImpl::setNameImpl(const std::string& threadName)
{
std::string realName = threadName;
if (threadName.size() > POCO_MAX_THREAD_NAME_LEN)
{
int half = (POCO_MAX_THREAD_NAME_LEN - 1) / 2;
std::string truncName(threadName, 0, half);
truncName.append("~");
truncName.append(threadName, threadName.size() - half);
realName = truncName;
}
if (realName != _name)
{
_name = realName;
}
}
std::string ThreadImpl::getNameImpl() const
{
return _name;
}
std::string ThreadImpl::getOSThreadNameImpl()
{
// return fake thread name;
return isRunningImpl() ? _name : "";
}
void ThreadImpl::setPriorityImpl(int prio)
{

View File

@ -41,7 +41,11 @@ public:
{
Thread* pThread = Thread::current();
if (pThread)
{
_threadName = pThread->name();
auto *pThreadImpl = reinterpret_cast<Poco::ThreadImpl *>(pThread);
_osThreadName = pThreadImpl->getOSThreadNameImpl();
}
_ran = true;
_event.wait();
}
@ -56,6 +60,11 @@ public:
return _threadName;
}
const std::string& osThreadName() const
{
return _osThreadName;
}
void notify()
{
_event.set();
@ -71,6 +80,7 @@ public:
private:
bool _ran;
std::string _threadName;
std::string _osThreadName;
Event _event;
};
@ -168,6 +178,7 @@ void ThreadTest::testThread()
assertTrue (!thread.isRunning());
assertTrue (r.ran());
assertTrue (!r.threadName().empty());
assertTrue (!r.osThreadName().empty());
}
@ -180,6 +191,19 @@ void ThreadTest::testNamedThread()
thread.join();
assertTrue (r.ran());
assertTrue (r.threadName() == "MyThread");
assertTrue (r.osThreadName() == r.threadName());
// name len > POCO_MAX_THREAD_NAME_LEN
Thread thread2("0123456789aaaaaaaaaa9876543210");
MyRunnable r2;
thread2.start(r2);
r2.notify();
thread2.join();
assertTrue (r2.ran());
assertTrue (r2.osThreadName() == r2.threadName());
assertTrue (r2.threadName().length() <= POCO_MAX_THREAD_NAME_LEN);
assertTrue (std::string(r2.threadName(), 0, 7) == "0123456");
assertTrue (std::string(r2.threadName(), r2.threadName().size() - 7) == "6543210");
}