LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2139|回复: 7

有关pthread_join()的问题

[复制链接]
发表于 2007-11-24 23:51:42 | 显示全部楼层 |阅读模式
请问一下,如果pthread_join()函数等待的那个线程异常终止了或者说突然core掉了,那么pthread_join()能够返回吗?

有没有一种方法能够检查一个线程的状态,当这个线程终止时(不管哪种形式的终止,正常/异常),能够重新把这个线程拉起来?

现在我想的方法是再另外起一个监视线程B调用pthread_join()函数等待被监视线程A,如果被监视线程A突然挂掉了,那么
pthread_join()函数会返回,这时,监视线程B重新调用pthread_create()重新创建一个线程C,这个线程C调用与被监视线程
A相同的线程处理函数,来达到继续处理线程A需要处理的任务的目的。

写了一段测试代码,当线程A正常终止时,上面的方法是可行的;现在的问题就是,如果线程A core dump,那上面那个方法还能生效吗?

P.S. 线程A的处理函数会有一个很长的处理逻辑或者无限循环处理某些任务。

测试代码如下:

  1. #include <stdio.h>
  2. #include <pthread.h>

  3. static pthread_t tid[2];

  4. void test1()
  5. {
  6.        printf("thread1 continue, tid[%d]\n", pthread_self());
  7.        sleep(5);
  8. }

  9. void test2()
  10. {
  11.        while(1) {
  12.                pthread_join(tid[0], NULL);
  13.                printf("thread2 continue, tid[%d]\n", pthread_self());

  14.                pthread_create(&tid[0], NULL, (void *(*)(void
  15. *))test1, NULL);

  16.        }
  17. }

  18. int main()
  19. {
  20.        int ret;

  21.        pthread_create(&tid[0], NULL, (void *(*)(void *))test1, NULL);
  22.        pthread_create(&tid[1], NULL, (void *(*)(void *))test2, NULL);

  23.        pthread_join(tid[1], NULL);
  24.        return 0;
  25. }
复制代码
 楼主| 发表于 2007-11-24 23:52:48 | 显示全部楼层

有关pthread_join()的问题

请问一下,如果pthread_join()函数等待的那个线程异常终止了或者说突然core掉了,那么pthread_join()能够返回吗?

有没有一种方法能够检查一个线程的状态,当这个线程终止时(不管哪种形式的终止,正常/异常),能够重新把这个线程拉起来?

现在我想的方法是再另外起一个监视线程B调用pthread_join()函数等待被监视线程A,如果被监视线程A突然挂掉了,那么
pthread_join()函数会返回,这时,监视线程B重新调用pthread_create()重新创建一个线程C,这个线程C调用与被监视线程
A相同的线程处理函数,来达到继续处理线程A需要处理的任务的目的。

写了一段测试代码,当线程A正常终止时,上面的方法是可行的;现在的问题就是,如果线程A core dump,那上面那个方法还能生效吗?

P.S. 线程A的处理函数会有一个很长的处理逻辑或者无限循环处理某些任务。

测试代码如下:

  1. #include <stdio.h>
  2. #include <pthread.h>

  3. static pthread_t tid[2];

  4. void test1()
  5. {
  6.        printf("thread1 continue, tid[%d]\n", pthread_self());
  7.        sleep(5);
  8. }

  9. void test2()
  10. {
  11.        while(1) {
  12.                pthread_join(tid[0], NULL);
  13.                printf("thread2 continue, tid[%d]\n", pthread_self());

  14.                pthread_create(&tid[0], NULL, (void *(*)(void*))test1, NULL);

  15.        }
  16. }

  17. int main()
  18. {
  19.        int ret;

  20.        pthread_create(&tid[0], NULL, (void *(*)(void *))test1, NULL);
  21.        pthread_create(&tid[1], NULL, (void *(*)(void *))test2, NULL);

  22.        pthread_join(tid[1], NULL);
  23.        return 0;
  24. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2007-11-25 00:23:49 | 显示全部楼层
真要core dump,那整个进程都终止了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-11-25 10:34:38 | 显示全部楼层
Post by realtang;1787277
真要core dump,那整个进程都终止了。


可能我说的不清楚,主要是处理线程意外挂起的现象,并且在多线程中,如果只是进程中其中一个线程core了,整个进程是不会终止的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-11-25 10:36:37 | 显示全部楼层
解决了,上面的方法可以解决被监视线程终止的情况,但是不能解决线程被意外挂起的情况。

利用自定义信号和alarm就可解决挂起问题
解决方法是装载两个信号处理函数并设定alarm,一个处理alarm超时时,利用上面的方法重新启动一个线程C处理线程A的任务,并重新设定alarm;一个处理自定义信号,比如SIGUSR1,方法是在被监视线程A的处理函数中利用raise()函数定期发送SIGUSR1信号,该信号处理函数当捕捉到这个信号时就重设alarm值,这样新的值会代替久的值,那么时钟就不会超时,如果一段时间后没有收到这个信号,则被监视线程A就可能被挂起了,于是会执行处理alarm超时的处理函数。
到此,两个方法同时使用就可监视线程A,当A意外终止或被挂起的时候可以将它拉起。

P.S. 这里的监视线程A的处理函数要循环处理某些任务,被认为是将会一直运行的线程,所以任何情况的终止和挂起都是不被允许的。

测试代码如下:

  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include <signal.h>
  4. #include <time.h>

  5. #define CHECK_THREAD_TIME 60

  6. static pthread_t tid[2];

  7. static void test1()
  8. {
  9.         while(1) {
  10.                 printf("thread1 continue, tid[%d]\n", pthread_self());
  11.                 raise(SIGUSR1);
  12.                 sleep(5);
  13.         }
  14. }

  15. static void test2()
  16. {
  17.         while(1) {
  18.                 pthread_join(tid[0], NULL);
  19.                 printf("thread2 continue, tid[%d]\n", pthread_self());

  20.                 pthread_create(&tid[0], NULL, (void *(*)(void *))test1, NULL);

  21.         }
  22. }

  23. static void
  24. overtime_handler(int signo)
  25. {
  26.         time_t tm;

  27.         //time alarm
  28.         printf("abnormal: thread has been hanged, time[%s], restart...\n", ctime(&tm));

  29.         pthread_create(&tid[0], NULL, (void *(*)(void *))test1, NULL);
  30.         alarm(CHECK_THREAD_TIME);
  31. }

  32. static void
  33. resetalarm_handler(int signo)
  34. {
  35.         int ret;

  36.         ret = alarm(CHECK_THREAD_TIME);
  37.         printf("oh yeah! thread is still running, after [%d] seconds alarm will overtime\n", ret);
  38. }

  39. int main()
  40. {
  41.         int ret;

  42.         struct sigaction sa;
  43.         memset(&sa, 0x0, sizeof(sa));
  44.         sa.sa_handler = overtime_handler;
  45.         sigaction(SIGALRM, &sa, NULL);

  46.         sa.sa_handler = resetalarm_handler;
  47.         sigaction(SIGUSR1, &sa, NULL);

  48.         alarm(CHECK_THREAD_TIME);

  49.         pthread_create(&tid[0], NULL, (void *(*)(void *))test1, NULL);
  50.         pthread_create(&tid[1], NULL, (void *(*)(void *))test2, NULL);

  51.         pthread_join(tid[1], NULL);
  52.         return 0;
  53. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2007-11-25 14:34:22 | 显示全部楼层
其实检测线程是否挂起也很容易,就跟heart beat的原理一样,用另外一个线程或进程不断的跟它通信(socket,信号,IPC消息队列),一旦没有响应,就说明它挂了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-11-26 08:26:08 | 显示全部楼层
Post by realtang;1787437
其实检测线程是否挂起也很容易,就跟heart beat的原理一样,用另外一个线程或进程不断的跟它通信(socket,信号,IPC消息队列),一旦没有响应,就说明它挂了。


正解,我就是使用的这种方法,呵呵。
回复 支持 反对

使用道具 举报

发表于 2007-11-27 09:27:20 | 显示全部楼层
占位贴,以后查起来方便点:sorry
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表