2012-02-28 55 views
3

我有一个关于pthread_kill()行为的问题。关于pthread_kill()行为

这里有一个小的代码我尝试:

void my_handler1(int sig) 
{ 
    printf("my_handle1: Got signal %d, tid: %lu\n",sig,pthread_self()); 
    //exit(0); 
} 

void *thread_func1(void *arg) 
{ 
    struct sigaction my_action; 
    my_action.sa_handler = my_handler1; 
    my_action.sa_flags = SA_RESTART; 
    sigaction(SIGUSR1, &my_action, NULL); 
    printf("thread_func1 exit\n"); 
} 


void *thread_func2(void *arg) 
{ 
    int s; 
    s = pthread_kill(tid1_g,SIGUSR1); 
    if(s) 
      handle_error(s,"tfunc2: pthread_kill"); 

    printf("thread_func2 exit\n"); 
} 


int main() 
{ 
    int s = 0; 
    pthread_t tid1; 

    s = pthread_create(&tid1,NULL,thread_func1,NULL); 
    if(s) 
      handle_error(s,"pthread_create1"); 

    tid1_g = tid1; 
    printf("tid1: %lu\n",tid1); 
    s = pthread_join(tid1,NULL); 
    if(s) 
      handle_error(s, "pthread_join"); 

    printf("After join tid1\n"); 

    pthread_t tid3; 
    s = pthread_create(&tid3,NULL,thread_func2,NULL); 
    if(s) 
      handle_error(s,"pthread_create3"); 

    s = pthread_join(tid3,NULL); 
    if(s) 
      handle_error(s, "pthread_join3"); 

    printf("After join tid3\n"); 
    return 0; 
} 

我得到的输出是:

tid1: 140269627565824 
thread_func1 exit 
After join tid1 
my_handle1: Got signal 10, tid: 140269627565824 
thread_func2 exit 
After join tid3 

所以,即使我一个线程调用pthread_kill()已经完成,该线程的处理程序仍然被调用。在线程不存在的情况下,pthread_kill()是否应该返回错误(ESRCH)?

回答

7

pthread_t的任何使用(*)为线程其寿命之后(即后pthread_join成功返回,或线程在分离状态终止后)的结果未定义行为。如果pthread_t仍然有效,您应该只预计ESRCH,即如果您还没有加入线程。否则所有投注都关闭。

注意:通过“使用”(*),我的意思是将它传递给标准库中的pthread_函数。据我所知,只是将它分配给另一个pthread_t变量或以其他方式在您自己的函数之间传递而不用“不使用”它不会导致UB。

3

据此SO thread说,传递一个信号给一个已经死了的线程(只有当线程被加入或退出)导致未定义的行为!

编辑:找到一个thread,它清楚地引用了最新的POSIX规范,它指示行为未定义。感谢R ..为正确的指针!

+0

只有当线程连接或分离时退出。如果线程已经死了,但仍然可以连接,那么它是非常明确的。 – 2012-02-28 19:07:24

+0

谢谢!更新了我的回答:) – 2012-02-28 19:09:35

+1

编辑不正确; POSIX说没有这样的事情。前一版本的POSIX(2001)错误地给出了这样的印象:如果“实现检测到”线程不再存在,则说几个函数“应该失败”。请注意,没有要求实施必须检测到这种情况;只有它,它确实需要使用特定的错误代码。许多执行者和应用程序作者错误地将此视为执行通常不可能做到的事情。 POSIX 2008已经解决了所有这些问题。 – 2012-02-28 19:15:29

0

问题asked here(如何确定pthread是否仍然存在)已被标记为与此问题重复。

但我相信这篇文章只是澄清了pthread_kill的行为,并确认它不保证正确的行为,如果pthread_kill被称为无效的ID。因此,pthread_kill不能用于知道线程是否存在,就像线程早先加入一样,ID将不会有效或将被重新使用,并且如果其已被分离,则资源可能具有相同的情况如果线程被终止,则会被重新利用。

因此,以确定是否线程处于活动状态(问题是特别要求可接合的线程),我能想到下面只有一个解决方案:

使用一些全局数据/内存,并且可以通过螺纹和两个访问存储线程状态需要确定的返回/退出状态。其他线程可以检查此数据/ locatin以获取其状态。 (显然这假定线程正常退出,即加入或分离)。

对于e.g:

Have a global bool named as "bTerminated" initialized with "FALSE" and in 
the handler function of this thread either make it as "TRUE" before 
returning or modify it once it is returned to the caller (i.e where you have 
called `pthread_join` for this thread). Check for this variable in any other 
threads where you want to know if this thread is alive. Probably it will be 
straight to implement such a logic which fits into your original code.