免费注册 查看新帖 |

Chinaunix

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

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 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2006-02-08 11:38 |显示全部楼层
多谢版主的回复。

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

论坛徽章:
0
3 [报告]
发表于 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
4 [报告]
发表于 2006-02-08 12:28 |显示全部楼层
如果大家方便,最好编译运行下.
我最奇怪的是 localtime_r 和 sem_wait() 的共同执行能影响线程1(f1)能否被线程2(f2)cancel掉。而sem_wait 又是一个cancellation point.

论坛徽章:
0
5 [报告]
发表于 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
}

论坛徽章:
0
6 [报告]
发表于 2006-02-08 12:56 |显示全部楼层
printf( "f2: join ok !\n" );

论坛徽章:
0
7 [报告]
发表于 2006-02-08 13:03 |显示全部楼层
不可能吧,是从第一篇copy的吗?

论坛徽章:
0
8 [报告]
发表于 2006-02-08 13:07 |显示全部楼层
晕! linux 2.4.20 , gcc 3.2.2  ?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP