【问题标题】:About pthread_kill() behavior关于 pthread_kill() 行为
【发布时间】:2012-03-18 06:06:05
【问题描述】:

我有一个关于 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)吗?

【问题讨论】:

    标签: c operating-system pthreads


    【解决方案1】:

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

    但我相信这篇文章只是澄清了pthread_kill 的行为,并确认如果使用不再有效的 ID 调用pthread_kill,它不能保证正确的行为。因此,pthread_kill 不能用于知道线程是否还活着,就好像线程之前加入了一样,ID 将无效或将被重新使用,如果它作为资源被分离也是如此如果线程被终止,可能已经被回收。

    因此,要确定线程是否处于活动状态(专门询问可连接线程的问题),我只能想到一种解决方案,如下所示:

    使用一些可以被两个线程访问的全局数据/内存,并将线程的返回/退出状态存储在那里。其他线程可以检查此数据/位置以获取其状态。 (显然,这假设线程正常退出,即加入或分离)。

    例如:

    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.
    

    【讨论】:

      【解决方案2】:

      据此SO thread 表示,将信号传递给已经死掉的线程(仅当线程被加入或退出时)会导致未定义的行为!

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

      【讨论】:

      • 仅当线程在分离时加入或退出。如果线程已死但仍可连接,则定义明确。
      • 编辑不正确; POSIX 没有说这样的话。 POSIX (2001) 的早期版本错误地给人的印象是,如果“实现检测到”线程不再存在,那么几个函数“将失败”。请注意,没有要求实现必须检测这种情况;仅此而已,它必须使用特定的错误代码。许多实现者和应用程序作者错误地将其理解为要求实现执行通常不可能的事情。 POSIX 2008 已修复所有这些问题。
      • 另请注意,两个版本(2001 和 2008)在其他地方(在 XSH 开头的线程的一般文本中)都是明确的,在线程生命周期结束后使用 pthread_t 会导致 UB .
      【解决方案3】:

      任何对pthread_t 的使用 (*) 在其生命周期之后(即在pthread_join 成功返回之后,或在线程以分离状态终止之后)导致未定义的行为。如果pthread_t 仍然有效,即如果您还没有加入线程,您应该只期待ESRCH。否则,所有赌注都将被取消。

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

      【讨论】:

        猜你喜欢
        • 2018-10-17
        • 2011-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-21
        • 2012-01-18
        • 1970-01-01
        相关资源
        最近更新 更多