Give our threads debugger-friendly names

This commit is contained in:
baldurk
2019-12-19 17:46:10 +00:00
parent 2620f0bb8c
commit 27098f8f70
20 changed files with 174 additions and 0 deletions
+4
View File
@@ -702,6 +702,7 @@ void CaptureContext::LoadCapture(const rdcstr &captureFile, const ReplayOptions
new LambdaThread([this, captureFile, opts, origFilename, temporary, local]() {
LoadCaptureThreaded(captureFile, opts, origFilename, temporary, local);
});
thread->setName(lit("LoadCapture"));
thread->selfDelete(true);
thread->start();
@@ -1095,6 +1096,7 @@ void CaptureContext::RecompressCapture()
LambdaThread *th = new LambdaThread([cap, destFilename, &progress]() {
cap->Convert(destFilename.toUtf8().data(), "rdc", NULL, [&progress](float p) { progress = p; });
});
th->setName(lit("RecompressCapture"));
th->start();
// wait a few ms before popping up a progress bar
th->wait(500);
@@ -1319,6 +1321,7 @@ bool CaptureContext::ImportCapture(const CaptureFileFormat &fmt, const rdcstr &i
[&progress](float p) { progress = 0.5f + p * 0.5f; });
file->Shutdown();
});
th->setName(lit("ImportCapture"));
th->start();
// wait a few ms before popping up a progress bar
th->wait(500);
@@ -1394,6 +1397,7 @@ void CaptureContext::ExportCapture(const CaptureFileFormat &fmt, const rdcstr &e
status = file->Convert(exportfile.c_str(), ext.toUtf8().data(), sdfile,
[&progress](float p) { progress = p; });
});
th->setName(lit("ExportCapture"));
th->start();
// wait a few ms before popping up a progress bar
th->wait(500);
@@ -158,6 +158,7 @@ static ShaderToolOutput RunTool(const ShaderProcessingTool &tool, QWidget *windo
process.moveToThread(mainThread);
});
thread->setName(lit("ShaderProcessingTool %s").arg(tool.name));
thread->moveObjectToThread(&process);
thread->start();
+63
View File
@@ -2275,6 +2275,7 @@ void ShowProgressDialog(QWidget *window, const QString &labelText, ProgressFinis
GUIInvoke::call(&dialog, [&dialog]() { dialog.closeAndReset(); });
});
progressTickerThread.setName(lit("Progress Dialog"));
progressTickerThread.start();
// show the dialog
@@ -2448,3 +2449,65 @@ void *AccessWaylandPlatformInterface(const QByteArray &resource, QWindow *window
QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
return native->nativeResourceForWindow(resource, window);
}
// Default Qt doesn't do this in release Qt builds, which is all we use
#if defined(Q_OS_WIN32)
#include <windows.h>
typedef HRESULT(WINAPI *PFN_SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
static void SetThreadNameWithException(const char *name)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)(&info));
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
}
}
void LambdaThread::windowsSetName()
{
// try to use the fancy modern API
static PFN_SetThreadDescription setThreadDesc = (PFN_SetThreadDescription)GetProcAddress(
GetModuleHandleA("kernel32.dll"), "SetThreadDescription");
if(setThreadDesc)
{
setThreadDesc(GetCurrentThread(), m_Name.toStdWString().c_str());
}
else
{
// don't throw the exception if there's no debugger present
if(!IsDebuggerPresent())
return;
SetThreadNameWithException(m_Name.toStdString().c_str());
}
}
#else
void LambdaThread::windowsSetName()
{
}
#endif
+10
View File
@@ -318,10 +318,15 @@ private:
QThread *m_Thread;
QSemaphore completed;
bool m_SelfDelete = false;
QString m_Name;
void windowsSetName();
public slots:
void process()
{
if(!m_Name.isEmpty())
windowsSetName();
m_func();
m_Thread->quit();
m_Thread = NULL;
@@ -342,6 +347,11 @@ public:
QObject::connect(m_Thread, &QThread::finished, m_Thread, &QThread::deleteLater);
}
void setName(QString name)
{
m_Name = name;
m_Thread->setObjectName(name);
}
void start(QThread::Priority prio = QThread::InheritPriority) { m_Thread->start(prio); }
bool isRunning() { return completed.available(); }
bool wait(unsigned long time = ULONG_MAX)
+3
View File
@@ -54,6 +54,7 @@ void ReplayManager::OpenCapture(const QString &capturefile, const ReplayOptions
m_Thread = new LambdaThread([this, proxyRenderer, capturefile, opts, progress]() {
run(proxyRenderer, capturefile, opts, progress);
});
m_Thread->setName(lit("ReplayManager"));
m_Thread->start(QThread::HighestPriority);
while(m_Thread->isRunning() && !m_Running)
@@ -185,6 +186,7 @@ rdcstr ReplayManager::CopyCaptureToRemote(const rdcstr &localpath, QWidget *wind
{
LambdaThread *thread = new LambdaThread([&lambda]() { lambda(NULL); });
thread->selfDelete(true);
thread->setName(lit("CopyCaptureToRemote"));
thread->start();
}
@@ -219,6 +221,7 @@ void ReplayManager::CopyCaptureFromRemote(const rdcstr &remotepath, const rdcstr
{
LambdaThread *thread = new LambdaThread([&lambda]() { lambda(NULL); });
thread->selfDelete(true);
thread->setName(lit("CopyCaptureFromRemote"));
thread->start();
}
+1
View File
@@ -2560,6 +2560,7 @@ void BufferViewer::populateBBox(PopulateBufferData *bufdata)
GUIInvoke::call(this, [this, bbox]() { UI_UpdateBoundingBox(*bbox); });
});
thread->setName(lit("BBox calc"));
thread->selfDelete(true);
thread->start();
@@ -585,6 +585,7 @@ void CaptureDialog::CheckAndroidSetup(QString &filename)
}
});
scan->setName(lit("CheckAndroidSetup"));
scan->start();
scan->deleteLater();
}
@@ -663,6 +664,7 @@ Would you like RenderDoc to try patching your package?
}
});
patch->setName(lit("Android patch"));
patch->start();
// wait a few ms before popping up a progress bar
patch->wait(500);
+4
View File
@@ -181,6 +181,7 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
}
}
});
m_RemoteProbe->setName(lit("Remote Probe"));
m_RemoteProbe->start();
SetTitle();
@@ -607,6 +608,7 @@ void MainWindow::OnCaptureTrigger(const QString &exe, const QString &workingDir,
callback(live);
});
});
th->setName(lit("ExecuteAndInject"));
th->start();
// wait a few ms before popping up a progress bar
th->wait(500);
@@ -1943,6 +1945,7 @@ void MainWindow::setRemoteHost(int hostIdx)
// update status
host.CheckStatus();
});
launchthread->setName(lit("Remote host launch"));
launchthread->start();
ShowProgressDialog(this, tr("Attempting to update remote server, please wait..."),
@@ -2017,6 +2020,7 @@ void MainWindow::setRemoteHost(int hostIdx)
m_Ctx.GetCaptureDialog()->UpdateRemoteHost();
});
});
th->setName(lit("Remote host check"));
th->selfDelete(true);
th->start();
}
+1
View File
@@ -713,6 +713,7 @@ void PythonShell::on_runScript_clicked()
});
});
thread->setName(lit("Python script"));
thread->selfDelete(true);
thread->start();
}
+4
View File
@@ -696,6 +696,8 @@ struct AndroidController : public IDeviceProtocolHandler
void ThreadEntry()
{
Threading::SetCurrentThreadName("AndroidController");
while(Atomic::CmpExch32(&running, 1, 1) == 1)
{
Threading::Sleep(5);
@@ -956,6 +958,8 @@ ExecuteResult AndroidRemoteServer::ExecuteAndInject(const char *a, const char *w
// we spin up a thread to Ping() every second, since starting a package can block for a long time.
volatile int32_t done = 0;
Threading::ThreadHandle pingThread = Threading::CreateThread([&done, this]() {
Threading::SetCurrentThreadName("Android Ping");
bool ok = true;
while(ok && Atomic::CmpExch32(&done, 0, 0) == 0)
ok = Ping();
+4
View File
@@ -154,6 +154,8 @@ struct ClientThread
static void InactiveRemoteClientThread(ClientThread *threadData)
{
Threading::SetCurrentThreadName("InactiveRemoteClientThread");
uint32_t ip = threadData->socket->GetRemoteIP();
{
@@ -209,6 +211,8 @@ static void InactiveRemoteClientThread(ClientThread *threadData)
static void ActiveRemoteClientThread(ClientThread *threadData,
RENDERDOC_PreviewWindowCallback previewWindow)
{
Threading::SetCurrentThreadName("ActiveRemoteClientThread");
Network::Socket *&client = threadData->socket;
#if ENABLED(RDOC_DEVEL)
+2
View File
@@ -2570,6 +2570,8 @@ void ReplayProxy::EndRemoteExecution()
void ReplayProxy::RemoteExecutionThreadEntry()
{
Threading::SetCurrentThreadName("RemoteExecutionThreadEntry");
// while we're alive
while(Atomic::CmpExch32(&m_RemoteExecutionKill, 0, 0) == 0)
{
+4
View File
@@ -100,6 +100,8 @@ rdcstr DoStringise(const PacketType &el)
void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *client)
{
Threading::SetCurrentThreadName("TargetControlClientThread");
Threading::KeepModuleAlive();
WriteSerialiser writer(new StreamWriter(client, Ownership::Nothing), Ownership::Stream);
@@ -375,6 +377,8 @@ void RenderDoc::TargetControlClientThread(uint32_t version, Network::Socket *cli
void RenderDoc::TargetControlServerThread(Network::Socket *sock)
{
Threading::SetCurrentThreadName("TargetControlServerThread");
Threading::KeepModuleAlive();
RenderDoc::Inst().m_SingleClientName = "";
+2
View File
@@ -145,6 +145,8 @@ void SetTLSValue(uint64_t slot, void *value);
// must typedef CriticalSectionTemplate<X> CriticalSection
void SetCurrentThreadName(const rdcstr &name);
typedef uint64_t ThreadHandle;
ThreadHandle CreateThread(std::function<void()> entryFunc);
uint64_t GetCurrentID();
@@ -38,3 +38,7 @@ uint64_t Timing::GetTick()
clock_gettime(CLOCK_MONOTONIC, &ts);
return uint64_t(ts.tv_sec) * 1000000000ULL + uint32_t(ts.tv_nsec & 0xffffffff);
}
void Threading::SetCurrentThreadName(const rdcstr &name)
{
}
@@ -40,3 +40,7 @@ uint64_t Timing::GetTick()
{
return mach_absolute_time();
}
void Threading::SetCurrentThreadName(const rdcstr &name)
{
}
+4
View File
@@ -38,3 +38,7 @@ uint64_t Timing::GetTick()
clock_gettime(CLOCK_MONOTONIC, &ts);
return uint64_t(ts.tv_sec) * 1000000000ULL + uint32_t(ts.tv_nsec & 0xffffffff);
}
void Threading::SetCurrentThreadName(const rdcstr &name)
{
}
@@ -24,6 +24,7 @@
#include "os/os_specific.h"
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
@@ -38,3 +39,8 @@ uint64_t Timing::GetTick()
clock_gettime(CLOCK_MONOTONIC, &ts);
return uint64_t(ts.tv_sec) * 1000000000ULL + uint32_t(ts.tv_nsec & 0xffffffff);
}
void Threading::SetCurrentThreadName(const rdcstr &name)
{
prctl(PR_SET_NAME, (unsigned long)name.c_str(), 0, 0, 0);
}
+2
View File
@@ -1346,6 +1346,8 @@ static GlobalHookData *globalHook = NULL;
// the global hook.
static void GlobalHookThread()
{
Threading::SetCurrentThreadName("GlobalHookThread");
// keep looping doing an atomic compare-exchange to check that finished is still 0
while(Atomic::CmpExch32(&globalHook->finished, 0, 0) == 0)
{
+49
View File
@@ -262,6 +262,55 @@ ThreadHandle CreateThread(std::function<void()> entryFunc)
return (ThreadHandle)h;
}
typedef HRESULT(WINAPI *PFN_SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription);
const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push, 8)
typedef struct tagTHREADNAME_INFO
{
DWORD dwType; // Must be 0x1000.
LPCSTR szName; // Pointer to name (in user addr space).
DWORD dwThreadID; // Thread ID (-1=caller thread).
DWORD dwFlags; // Reserved for future use, must be zero.
} THREADNAME_INFO;
#pragma pack(pop)
static void SetThreadNameWithException(const char *name)
{
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = name;
info.dwThreadID = GetCurrentThreadId();
info.dwFlags = 0;
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR *)(&info));
}
__except(EXCEPTION_CONTINUE_EXECUTION)
{
}
}
void SetCurrentThreadName(const rdcstr &name)
{
// try to use the fancy modern API
static PFN_SetThreadDescription setThreadDesc = (PFN_SetThreadDescription)GetProcAddress(
GetModuleHandleA("kernel32.dll"), "SetThreadDescription");
if(setThreadDesc)
{
setThreadDesc(GetCurrentThread(), StringFormat::UTF82Wide(name).c_str());
}
else
{
// don't throw the exception if there's no debugger present
if(!IsDebuggerPresent())
return;
SetThreadNameWithException(name.c_str());
}
}
uint64_t GetCurrentID()
{
return (uint64_t)::GetCurrentThreadId();