免费注册 查看新帖 |

Chinaunix

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

pthread_cancel 的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-02-08 11:28 |只看该作者 |倒序浏览
很简单的情况,创建两个线程,第2个去cancel第1个。
但如果 f1 中的 localtime_r 和 sem 同时打开执行, f2 在 join时阻塞;
如果只开任何一个, f2 的join 成功。
困惑中,请高手指点! (redhat 8.0)

#include <pthread.h>
#include <semaphore.h>
#include <stdio.h>
#include <time.h>

#define LEN 128
#define PATH "./"

pthread_t tid[2];

char filename[LEN];
FILE *f;

void *f1(void *p)
{
    pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

    printf( "in %s\n", __FUNCTION__ );
    time_t ta;
    struct tm tb;

    ta = time( NULL );
#if 1
    localtime_r( &ta, &tb );
#else
    memset( &tb, 0, sizeof(tb) );
#endif
    snprintf( filename, LEN, "%s%d_%d_%d-%d_%d.data",
                        PATH,
                        tb.tm_year + 1900, tb.tm_mon, tb.tm_mday,
                        tb.tm_hour, tb.tm_min);

    printf( "Backup file is  %s\n", filename);
    f = fopen( filename, "w" );
    if( ! f)
        perror( "ERROR: OpenBackup" );


#if 1
    sem_t sem;
    sem_init( &sem, 0, 0);
    sem_wait( &sem );
#else
    sleep(1000);
#endif
}

void *f2(void *p)
{
    pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

    printf( "in %s\n", __FUNCTION__ );

    pthread_cancel( tid[0] );
    printf( "f2: join ...\n");
    pthread_join( tid[0], NULL);

    printf( "f2: join ok !\n" );
}


int main()
{

  pthread_attr_t tattr;
  pthread_attr_init( &tattr);
  pthread_attr_setdetachstate( &tattr, PTHREAD_CREATE_JOINABLE);

  pthread_create( &tid[0], &tattr, f1, NULL);
  sleep(5);
  pthread_create( &tid[1], &tattr, f2, NULL);

  printf( "press ...\n" );
  getchar();
}

[ 本帖最后由 andyY 于 2006-2-8 11:31 编辑 ]

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
2 [报告]
发表于 2006-02-08 11:34 |只看该作者
f2的阻塞原因应该是 f1中sem_wait( &sem );的原因吧.
没有在其他线程中sem_post的原因.

论坛徽章:
0
3 [报告]
发表于 2006-02-08 11:38 |只看该作者
多谢版主的回复。

f2 还有其它工作,用 sem 来作阻塞,完整的是有其它线程 post这个全局sem的。这里简化了下。
但这些都是正常使用,线程阻塞一样可以被 cancel 吧!

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
4 [报告]
发表于 2006-02-08 11:42 |只看该作者
原帖由 andyY 于 2006-2-8 11:38 发表
多谢版主的回复。

f2 还有其它工作,用 sem 来作阻塞,完整的是有其它线程 post这个全局sem的。这里简化了下。
但这些都是正常使用,线程阻塞一样可以被 cancel 吧!


至于阻塞是否能被cancel掉.要看具体的实现了.
我也去查查相关的资料.
我一直用多进程的模型.

能说说cancel的真正目的是什么吗? 多谢.

论坛徽章:
0
5 [报告]
发表于 2006-02-08 12:11 |只看该作者
pthread_cancel() 在posix中有叙述:将其称之为“不安全的上下文”

一个thread中,处于完全封闭的环境,没有任何代码出口,呵呵,pthread_cancel的做法就值得怀疑了,安全吗?

我一直坚持认为pthread_cancel是个危险的函数,如果在代码中遇到需要停止thread的流程,我都要在thread的代码中预留一个标记以便thread的退出:
while(1)
{
    if( thread_stop == 1 )
    {
         pthread_exit(0);
    }
}

强烈建议thread的出口使用pthread_exit(), 不要简单的使用return,这二者之间对于代码现场的清理是不同的

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
6 [报告]
发表于 2006-02-08 12:24 |只看该作者
原帖由 liuzhuan23 于 2006-2-8 12:11 发表
pthread_cancel() 在posix中有叙述:将其称之为“不安全的上下文”

一个thread中,处于完全封闭的环境,没有任何代码出口,呵呵,pthread_cancel的做法就值得怀疑了,安全吗?

我一直坚持认为pthread_cance ...


说的有一定道理. 我想轮旬的机制有些浪费资源.应该采取其他方式.

我想LZ 不能pthread_cancel的原因 是否应该理解为.持有信号量不可以被cancel??

论坛徽章:
0
7 [报告]
发表于 2006-02-08 12:25 |只看该作者
5楼说得有些道理。不过当
while(1)
{
    if( thread_stop == 1 )
    {
         ...//含阻塞的业务过程
         pthread_exit(0);
    }
}
如果持续阻塞,thread_stop 没法检查退出!

另外thread的封闭性有 pthread_cleanup_xx 来作些处理:Cleanup handlers are functions that get called  when  a  thread  termi- nates,  either  by  calling pthread_exit(3) or !!! because of cancellation !!!.
通常我是配合用,应该没有问题的。

论坛徽章:
0
8 [报告]
发表于 2006-02-08 12:28 |只看该作者
如果大家方便,最好编译运行下.
我最奇怪的是 localtime_r 和 sem_wait() 的共同执行能影响线程1(f1)能否被线程2(f2)cancel掉。而sem_wait 又是一个cancellation point.

论坛徽章:
0
9 [报告]
发表于 2006-02-08 12:37 |只看该作者
1 sem_wait的状态是可以被signal中断
2 sem_wait的状态可不可以被cancel中断我没有试验过,所以我也不能下结论
3 从LZ的代码流程来看,很明显遇到了sem_wait指令之后并没有sem_post,导致cancel阻塞
4 斑竹说:“我想轮旬的机制有些浪费资源.应该采取其他方式”,呵呵,这我暂时还没有太好的方法^_^,如果斑竹是担心时钟周期占用的问题,使用其它辅助手段可以缓解

论坛徽章:
0
10 [报告]
发表于 2006-02-08 12:43 |只看该作者
man sem_wait:
  CANCELLATION
       sem_wait is a cancellation point.
  不管是否sem_post, 始终是cancellation point.

程序的结果:
1、仅执行 localtime_r ,可被cancel
2、仅执行 sem_wait, 可被cancel
3、同时执行 localtime_r 和sem_wait, 不能被cancel
这是怎么回事呢?

void *f1(void *p)
{
    pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

    printf( "in %s\n", __FUNCTION__ );
    time_t ta;
    struct tm tb;

    ta = time( NULL );
#if 1
    localtime_r( &ta, &tb );
#else
    memset( &tb, 0, sizeof(tb) );
#endif
   
   //...

#if 1
    sem_t sem;
    sem_init( &sem, 0, 0);
    sem_wait( &sem );
#else
    sleep(1000);
#endif
}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP