免费注册 查看新帖 |

Chinaunix

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

[C++] pthread_cancel c++ [复制链接]

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-07-05 17:04 |只看该作者 |倒序浏览
本帖最后由 chenzhanyiczy 于 2013-07-05 17:06 编辑
  1. class Info
  2. {
  3. public:
  4.     ~Info()
  5.     {
  6.         printf("~Info()\n");        //-----1
  7.     }
  8. };

  9. void thread_cleanup(void* arg)
  10. {
  11.                 printf("thread id=%lu cleanup\n",pthread_self());            //-----2

  12. }

  13. void*  func(void  *arg)
  14. {
  15.      int tick;

  16.     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  17.     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,   NULL);
  18.    
  19.     Info info;
  20.     pthread_cleanup_push(thread_cleanup,NULL);

  21.     while(1)
  22.       {
  23.            tick++;
  24.            sleep(1);                //-----3
  25.   }

  26.     pthread_cleanup_pop(0);
  27.     return NULL;
  28. }

  29. int main()
  30. {
  31.     pthread_t thread[1];

  32.     pthread_create(&thread[0],   &attr,   func,   NULL) ;

  33.     sleep(4);

  34.     if(!pthread_cancel(thrd[0]))
  35.       printf("cancel ok\n");

  36.     sleep(1000);
  37. }
复制代码
很简单的一段测试线程取消的代码。

首先,不管是否3有无,线程都可以被取消退出。
再者:
如果把3去掉,那么1和2都不对打印
如果保留3,那么1和2都打印
也就是说,加了个sleep(不单单是sleep,凡是系统调用都可以),就能析构栈上的局部变量和调用cleanup函数;不加,则不会。

PS:
0、pthread_cancel是通过发送信号实现的,信号值是32。具体可看glibc pthread_cancel.c源码
1、查看过kernel 信号部分源码,没发现阻塞系统调用和死循环运行,两者在收到信号后,有什么不同的处理情况。
2、从glibc相关源码,可以看出,局部对象的析构和cleanup情况都是通过_Unwind_ForcedUnwind()实现的,这个具体到c++,就是在libsupc++/eh_personality.cc实现的.
   当然如果是c的话,是不同的,通过setlongjmp实现

想来想去,应该是跟c++栈unwind有关,但想不明白为啥系统调用对栈unwind有什么影响?

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
2 [报告]
发表于 2013-07-05 20:25 |只看该作者
本帖最后由 myworkstation 于 2013-07-07 16:04 编辑

因为加上sleep线程就成为 Cancel-Safe的。而使用Asynchronous cancellation模式时Cancel-Safe的才是Asynchronous-Cancel-Safety的。当取消的类型为PTHREAD_CANCEL_ASYNCHRONOUS时,新到的或未决的取消请求可能在任意时刻起作用.只有从一个线程中调用cancel-safe的函数时这个线程才是异步可取消的。不然不能保证cleanup handler被调用。C++的构造,析构函数都不是Cancel-Safe的所以也不能保证被执行(这个取决于实现LLVM和GCC的行为不同)。大部分库函数都不是async-cancel-safe的。linux相关文档没有明确说明哪些函数是async-cancel-safe的。posix标准只规定了三个async-cancel-safe的函数:pthread_cancel(), pthread_setcancelstate(), and pthread_setcanceltype()。




man

When cancelability is enabled and the cancelability type is PTHREAD_CANCEL_ASYNCHRONOUS, new or pending cancellation requests may be acted upon at any time。only functions that are cancel-safe may be called from a thread that is asynchronously cancelable.


POSIX :

Async-Cancel Safety
A function is said to be async-cancel-safe if it is written in such a way that entering the function with asynchronous cancelability enabled will not cause any invariants to be violated, even if a cancellation request is delivered at any arbitrary instruction. Functions that are async-cancel-safe are often written in such a way that they need to acquire no resources for their operation and the visible variables that they may write are strictly limited.
Any routine that gets a resource as a side-effect cannot be made async-cancel-safe (for example, malloc()). If such a routine were called with asynchronous cancelability enabled, it might acquire the resource successfully, but as it was returning to the client, it could act on a cancellation request. In such a case, the application would have no way of knowing whether the resource was acquired or not.
Indeed, because many interesting routines cannot be made async-cancel-safe, most library routines in general are not async-cancel-safe. Every library routine should specify whether or not it is async-cancel safe so that programmers know which routines can be called from code that is asynchronously cancelable

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
3 [报告]
发表于 2013-07-06 19:40 |只看该作者
很奇怪, 只要被取消应该都执行的, 除非cancel在push之前, 但你加了sleep的.

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
4 [报告]
发表于 2013-07-08 09:50 |只看该作者
回复 2# myworkstation


    不是这个原因,把上面的换成用gcc编译,也就是纯c的话,无论有没有sleep()都是正常的。

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
5 [报告]
发表于 2013-07-08 17:04 |只看该作者
回复 4# chenzhanyiczy


    我之前写了一些文档规定的东东,实际上posix明确规定了c如果处理这种情况,但对C++没作规定,g++使用异常来实现stack unwinding。如果在你写的那个while循环中没有任何其它调用,只有简单语句赋值的话将不会导致C++的CRT产生异常,线程被直接终止,这应该是CRT的实现不完善造成的,而且C++在这方面也没什么可移植性,每个平台可能都不一样(MACOS,AIX等)。无论是C还是C++对pthread_cancel的调用都会导至系统发出一个SIGRTMIN信号来终止线程,在C++的情况下可能在循环中含有检查信号的调用时才会正常生成异常,从而让线程肯恢复执行始可以做stack unwinding也能让clean handler执行。而c的crt好像没这个特殊要求。

论坛徽章:
1
申猴
日期:2014-02-11 14:50:31
6 [报告]
发表于 2013-07-09 09:54 |只看该作者
本帖最后由 chenzhanyiczy 于 2013-07-09 09:55 编辑

回复 5# myworkstation


    不是说不对,但这样的猜测要有依据(标准或者代码证实等)

    之前说过,检查信号处理过程在有没有sleep都是一样的,这点可以确定(具体可以看看kernel源码)

   现在就是想找到为什么没加sleep就不会stack unwind的原因,具体到代码。

   gnu c++的stack unwind处理应该放在libsupc++/eh_personality.cc里
  
PS:
1、不用再讨论c的情况了,因为c方面完全没有问题,实现原理都在glibc里,可以看看

论坛徽章:
17
处女座
日期:2013-08-27 09:59:352015亚冠之柏太阳神
日期:2015-07-30 10:16:402015亚冠之萨济拖拉机
日期:2015-07-29 18:58:182015年亚洲杯之巴勒斯坦
日期:2015-03-06 17:38:17摩羯座
日期:2014-12-11 21:31:34戌狗
日期:2014-07-20 20:57:32子鼠
日期:2014-05-15 16:25:21亥猪
日期:2014-02-11 17:32:05丑牛
日期:2014-01-20 15:45:51丑牛
日期:2013-10-22 11:12:56双子座
日期:2013-10-18 16:28:17白羊座
日期:2013-10-18 10:50:45
7 [报告]
发表于 2013-07-09 11:41 |只看该作者
回复 6# chenzhanyiczy


    现有的标准对C++在这方面的行为根本没什么具体的规定,所以从标准上来讲对C++来说就是没标准,完全看具体的平台实现。至于GCC ,我觉得这个地方应该找到你感兴趣的东西。代码太多我就不去看了。你有兴趣看的话可以把研究的结果回在贴子里, http://thread.gmane.org/gmane.comp.gcc.help/41456
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP