微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

查找僵尸线程的来源

我有一个应用程序,我敢肯定“泄漏”线程忘记调用pthread_join。 所以他们的堆栈没有被清理,随着时间的推移会消耗大量的虚拟地址空间。

有没有办法在创build这些线程的软件中find一个地方,或者至less在退出之前找出这些线程正在做什么?

我的应用程序很大,并创build了很多正确连接的线程。 所以捕捉所有的pthread操作是不切实际的。 我需要更精确的东西。

我能够想出一个我认为正在发生的孤立的复制者。

hover子窗口时更改光标

如何将64位整数转换为char数组并返回?

屏蔽图书馆泄漏的应用程序

从c ++调用lib文件中的c函数

自定义的linux内核系统调用中强制执行代码

#include <pthread.h> #include <unistd.h> void* worker (void* unusued) { // Do nothing } int main() { pthread_t thread_id; for(int i=0; i < 2000; i++) { pthread_create(&thread_id,NULL,&worker,NULL); } sleep(1000); return 0; }

运行后,“top”显示16GB的虚拟地址空间被占用

但'ps'和'gdb'只显示一个线程

我有我的应用程序中的一切资源。 所以我可以添加任何代码或其他所需的仪器。

换句话说,上面的应用程序正在运行的实例如何发现它有2000个“丢失”线程以及如何发现他们执行了worker()函数

使用gSoap进行asynchronous,确认的点对点连接

将vkCode和scanCode转换为有意义的字符

用户模式访问Windows Native API

为什么Boost.Python示例构build失败?

如何在linux内核中实现clone(2)系统调用的另一个变种?

好问题。 一个可能的答案是使用libpthread插器。 看到这篇文章

让我们让你的测试程序更有趣一点,所以它只“泄漏”了几个线程,并加入其中大部分:

#include <pthread.h> #include <unistd.h> void* worker(void* unusued) { // Do nothing } int main() { pthread_t thread_id; for (int i = 0; i < 10; i++) { pthread_create(&thread_id,(void*)i); if (i != 4 && i != 7) pthread_join(thread_id,NULL); } sleep(1000); return 0; }

现在让我们为pthread_create和pthread_join构建一个插入器:

#include <assert.h> #include <dlfcn.h> #include <pthread.h> #include <map> static pthread_mutex_t mtx; typedef std::pair<void *,void *> elem_t; typedef std::map<pthread_t,elem_t> map_t; static map_t thr_map; extern "C" int pthread_create(pthread_t *tid,const pthread_attr_t *attr,void *(*start_routine)(void*),void *arg) { static __decltype(pthread_create) *real = reinterpret_cast<__decltype(pthread_create) *>(dlsym(RTLD_NEXT,"pthread_create")); int rc = (*real)(tid,attr,start_routine,arg); if (rc == 0) { pthread_mutex_lock(&mtx); thr_map[*tid] = std::make_pair((void*)start_routine,arg); pthread_mutex_unlock(&mtx); } return rc; } extern "C" int pthread_join(pthread_t tid,void **arg) { static __decltype(pthread_join) *real = reinterpret_cast<__decltype(pthread_join) *>(dlsym(RTLD_NEXT,"pthread_join")); int rc = (*real)(tid,arg); if (rc == 0) { pthread_mutex_lock(&mtx); const auto it = thr_map.find(tid); assert(it != thr_map.end()); thr_map.erase(it); pthread_mutex_unlock(&mtx); } return rc; }

构建它: g++ -g -fPIC -shared -o thr.so thr.cc -ldl -std=c++11并使用它:

LD_PRELOAD=./thr.so ./a.out & [1] 37057 gdb -q -p 37057 Attaching to process 37057 Reading symbols from /tmp/a.out...done. [Thread debugging using libthread_db enabled] Using host libthread_db library "/usr/lib64/libthread_db.so.1". 0x00007f95831a2f3d in nanosleep () at ../sysdeps/unix/syscall-template.S:81 81 ../sysdeps/unix/syscall-template.S: No such file or directory. (gdb) set print pretty (gdb) p thr_map $1 = std::map with 2 elements = { [140280106567424] = { first = 0x40069d <worker(void*)>,second = 0x7 },[140280114960128] = { first = 0x40069d <worker(void*)>,second = 0x4 } }

Voilà:你现在知道哪些线程没有被加入,哪些线程被调用,以及给了什么参数。

编辑

我的应用程序是静态链接

在这种情况下,链接器--wrap=pthread_create和--wrap=pthread_join是你的朋友。 文档在这里

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐