免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 7165 | 回复: 7
打印 上一主题 下一主题

[函数] [结贴]pthread线程清理和资源回收问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-08-17 11:26 |只看该作者 |倒序浏览
本帖最后由 davelv 于 2010-09-28 09:35 编辑

问题1、请求撤销线程,而且线程亦被撤销掉,但是注册的线程清理函数没有运行。

现有四个函数分别是,主函数,线程工作函数,线程监视函数,线程清理函数。
其中主函数负责建立工作线程和监视线程,而后为监视线程生产资源。

  1. int scheduler_listen(int sock)
  2. {
  3.         int i ,fd ,ret;

  4.         pthread_attr_init(&thread_attr);
  5.         pthread_attr_setstacksize(&thread_attr, 1024*1024);
  6.         pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
  7.         //建立工作线程
  8.         for (i=0; i<SCAN_THREAD_NUM; i++) {
  9.                 memset(&thread_param[i], 0x00, sizeof(THREAD_PARAM));

  10.                 thread_param[i].exec_time = -1;

  11.                 ret = pthread_create(&(thread_param[i].scan_thread), &thread_attr, loop_scanfile, (void *)&thread_param[i]);
  12.                 if (ret != 0) {
  13.                         //出错
  14.                         return -1;
  15.                 }
  16.         }
  17.         //建立监视线程
  18.         pthread_t psd;
  19.         pthread_create(&psd, &thread_attr, status_daemon, NULL);

  20.         //block self!
  21.         while(1)
  22.         {
  23.                 //生产资源
  24.         }
  25.         puts("exit!");
  26.         return 0;
  27. }
复制代码
工作线程主要是处理主函数生产的资源。

  1. void *loop_scanfile(void *param)
  2. {

  3.         struct cancel_param cp;
  4.         //初始化部分
  5.        
  6.         //注册清理函数
  7.         pthread_cleanup_push(thread_cleanup, &cp);
  8.         while(1) {
  9.                 //获取资源
  10.                 //处理

  11.         }//end while(1)
  12.         pthread_cleanup_pop(0);

  13.         return NULL;
  14. }
复制代码
监视函数是为了监视工作线程是否超时,超时则请求撤销该线程,并新建一个工作线程

  1. void *status_daemon(void *a)
  2. {
  3.         int i;
  4.         time_t now;
  5.         while(1)
  6.         {
  7.                 //休眠
  8.                 sleep(5);
  9.                
  10.                 time(&now);
  11.                 for(i=0; i<SCAN_THREAD_NUM; i++)
  12.                 {        //检测超时
  13.                         if((thread_param[i].exec_time>0) && (now-thread_param[i].exec_time >config.timeout) )
  14.                         {
  15.                                 printf("Scan thread timeout, restart it!\n");

  16.                                 //请求撤销
  17.                                 pthread_cancel(thread_param[i].scan_thread);
  18.                                 //新建线程
  19.                                 if ( pthread_create(&(thread_param[i].scan_thread), NULL, loop_scanfile, (void *)&thread_param[i]) != 0)
  20.                                 {
  21.                                         gate_print("%sScan thread recreate failed!",ERRSTR);
  22.                                         exit(-1);

  23.                                 }
  24.                         }
  25.                 }

  26.         }
  27.         return NULL;
  28. }
复制代码
线程清理函数主要是负责当工作线程被撤销时,回收正在使用的资源。

  1. void thread_cleanup(void *param)
  2. {
  3.         struct cancel_param *cp = (struct cancel_param*)param;
  4.         puts("Cleaning");
  5.         //清理资源       
  6. }
复制代码
在线程超时后,没有看到清理函数输出的内容,用过pstree查看进程信息,发现线程已经取消掉,但是资源未释放内存占用越来越大。这是为什么呢?

问题2、分离属性的线程运行完毕后或者撤消后,什么样的资源是由系统自动回收的?堆分配的资源系统会自动回收么?和joinable的线程在资源处理上有什么分别?看了一些资料,写都不是很详细,麻烦诸位给点详细的资料。

论坛徽章:
0
2 [报告]
发表于 2010-08-17 11:40 |只看该作者
借楼主的帖提个问题:

线程函数的返回值哪里获得的?

比如

void *test(void *ptr)
{
     int a=0;
     return((void*)a);
}
怎么获得a的值?pthread_create里面吗?

论坛徽章:
0
3 [报告]
发表于 2010-08-17 11:42 |只看该作者
回复 2# jt_feelcool


    使用pthread_join()函数,但是不能用在已分离的线程上,线程默认是可以join的。

论坛徽章:
0
4 [报告]
发表于 2010-08-17 11:50 |只看该作者
回复  jt_feelcool


    使用pthread_join()函数,但是不能用在已分离的线程上,线程默认是可以join的 ...
davelv 发表于 2010-08-17 11:42



    多谢大侠

论坛徽章:
0
5 [报告]
发表于 2010-08-17 13:53 |只看该作者
回复 1# davelv


    不管哪种属性,堆上申请的必须手工释放,但是如果是分离属性的线程,自身的栈等资源都会自行释放.

论坛徽章:
0
6 [报告]
发表于 2010-08-17 13:58 |只看该作者
回复 1# davelv
  1. #include <pthread.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #include <unistd.h>

  5. #define N   2

  6. struct thread_st {
  7.     pthread_t ptid;
  8.     time_t ctime;
  9. };

  10. struct thread_st pst[N];

  11. void *loop(void *);
  12. void *monitor(void *);

  13. int main()
  14. {
  15.     size_t i;
  16.     for (i = 0; i < N; ++i) {
  17.         pthread_create(&pst[i].ptid, NULL, loop, pst + i);
  18.         pst[i].ctime = time(NULL);
  19.     }
  20.     pthread_t ptid;
  21.     pthread_create(&ptid, NULL, monitor, NULL);
  22.    
  23.     while (1) sleep(10);

  24.     return 0;
  25. }

  26. void fclean(void *p)
  27. {
  28.     struct thread_st *pst = p;
  29.     printf("%d cleanup, exit\n", (int)pst->ptid);
  30. }

  31. void *loop(void *p)
  32. {
  33.     struct thread_st *pst = p;
  34.     pthread_cleanup_push(fclean, p);
  35.     while (1) {
  36.         printf("%d running\n", (int)pst->ptid);
  37.         sleep(1);
  38.     }
  39.     pthread_cleanup_pop(0);
  40.     return 0;
  41. }

  42. void *monitor(void *p)
  43. {
  44.     size_t i;
  45.     while (1) {
  46.         for (i = 0; i < N; ++i) {
  47.             if (time(NULL) - pst[i].ctime > 3) {
  48.                 pthread_cancel(pst[i].ptid);
  49.                 pthread_join(pst[i].ptid, NULL);
  50.                 pthread_create(&pst[i].ptid, NULL, loop, pst + i);
  51.                 pst[i].ctime = time(NULL);
  52.             }
  53.         }
  54.         sleep(1);
  55.     }
  56.     return 0;
  57. }
复制代码
我模拟你的程序,写了测试程序,线程清理函数是执行了的。
一个 pthread_cancel 并不等待线程退出,也就是说这个函数调用后,进程仍然在,这个时候马上创建新线程,并使用这个插槽,相当与新旧线程共用一个插槽,资源泄漏是不是和这个有关。
我的程序里增加了join,cancel之后,等待老线程退出,才创建新的线程。

问题2,我碰到的情况是,如果不是detach的线程,只有join才会回收线程本身的资源,这些不包括分配在堆上的内存。如果不join,且没有detach,则线程自身的资源也不回收,频繁的创建/删除进程,这个资源浪费,也很可观。

论坛徽章:
0
7 [报告]
发表于 2010-08-17 17:39 |只看该作者
我的线程插槽和需要清理的数据并不冲突,所以不会出现这样的问题。
而且我也试过join,但是没有效果。
都不知道到底是哪里出问题了头大。。
谢谢楼上还有5楼的回答

论坛徽章:
0
8 [报告]
发表于 2010-09-28 09:34 |只看该作者
最后的结果是,我在线程里面调用的某个函数会影响线程的清理。把清理写到线程结束后临时解决了此问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP