一种工具方法
您可以使用 Valgrind 来帮助解决这个问题(通过它的 Helgrind 工具),但它需要对代码进行少量修改。对于每个线程,在创建线程时使线程锁定一个唯一的互斥锁,并在线程退出时释放互斥锁。然后,当在 Helgrind 下运行时,如果程序终止时线程尚未退出,您将收到警告,因为线程仍将锁定互斥锁。考虑这个示例线程启动例程:
void * thread_start (void *arg)
{
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mutex);
// ...
// Here the thread does whatever it normally does
// ...
// Unlock the mutex before exiting
pthread_mutex_unlock(&mutex);
}
只需使用 Valgrind 的 Helgrind 工具运行程序,如下所示:
$ valgrind --tool=helgrind ./
如果程序终止时线程没有退出,那么 Helgrind 会产生如下警告:
==2203== 线程 #2 已创建
==2203== 在 0x31C96D3CDE:克隆(在 /lib64/libc-2.5.so 中)
==2203== 0x31CA206D87:pthread_create@@GLIBC_2.2.5(在 /lib64/libpthread-2.5.so 中)
==2203== 由 0x4A0B206:pthread_create_WRK (hg_intercepts.c:229)
==2203== 由 0x4A0B2AD: pthread_create@* (hg_intercepts.c:256)
==2203== by 0x40060A: main (main.c:26)
==2203==
==2203== 线程 #2:退出线程仍然持有 1 个锁
==2203== 在 0x4005DD:thread_start (main.c:13)
==2203== by 0x4A0B330: mythread_wrapper (hg_intercepts.c:201)
==2203== by 0x31CA20673C: start_thread (in /lib64/libpthread-2.5.so)
==2203== 由 0x31C96D3D1C:克隆(在 /lib64/libc-2.5.so 中)
如果您没有在线程可能退出的任何地方添加互斥锁解锁代码(例如,使用pthread_exit),使用此方法会出现误报,但一旦识别出此类误报,就很容易修复。
另一种方法(推荐)
说了以上所有,这可能不是我自己会采取的方法。相反,我会编写程序,使其无法在所有线程退出之前终止。实现这一点的最简单方法是在从main 返回之前从主线程调用pthread_exit。这样做意味着只要任何其他线程仍在运行,该进程就会保持活动状态。
如果您采用这种方法,并且进程没有在您期望的时候退出,那么您就知道线程仍在运行。然后,您可以将调试器附加到进程以确定哪些线程仍在运行以及它们在做什么。