如何同步pthread_kill?

时间:2018-04-04 12:11:59

标签: multithreading pthreads signals

我正在启动一堆可连接的工作线程,main()等待它们用pthread_join()完成。但是,在工作线程完成任务之前,用户可以在终端上点击 CTRL + C 。我的理解是任何线程都可以得到信号,所以我的所有工作线程在启动时调用pthread_sigmask()并阻塞SIGINT CTRL + C 信号)。这会导致信号被复制到其他线程main()。这样我知道至少main()肯定会得到信号。

我在main()上定义了一个信号处理函数,以便main()获取信号并杀死所有工作线程并从一个地方释放资源。问题是这是异步发生的。我从pthread_kill()调用main(),然后尝试工作线程正在使用的free()资源,并且它仍在运行,因为信号是异步调度的。

如果我从pthread_kill(SIGTERM, ...)拨打main()来杀死线程main()也会被杀死,do_thread_cleanup(i)永远不会被调用:

int main () {

    signal (SIGINT, signal_handler);

    for (i = 0; i < num_thd; i++) {
        pthread_create(thread_init, ...);
    }

    for (i = 0; i < num_thd; i++) {
        pthread_join(...);
    }

    return 0;
}

void signal_handler(int signal) {
    for (i = 0; i < num_thd; i++) {
        pthread_kill(pthread_t, SIGINT);
        pthread_join(pthread_t, ...);
        do_thread_cleanup(i);  // Calls functions like free() and close()
    }
}

void thread_init() {
    sigset_t sigset;
    sigemptyset(&sigset);
    sigaddset(&sigset, SIGINT);
    pthread_sigmask(SIG_BLOCK, &sigset, NULL);
    do_stuff_in_a_loop();
}

如何在没有SIGKILL接收该信号并自行查杀的情况下将main()发送给某个帖子?或者,我如何等待线程退出?

在阅读其他SO帖子后,讨论了如何使用pthread_cleanup_push()pthread_cleanup_pop(),但这并不允许我检查一个中心位置,即所有线程都被杀死并释放其资源。< / p>

1 个答案:

答案 0 :(得分:2)

简短的回答是你做不到;但你可以做点接近。

Free(),malloc()以及通向它们的所有路径都不是信号安全的;所以你不能从信号处理程序中调用它们。这些函数很少会注意到信号(重新)进入,因此可能导致不可预测的行为。

一个好的模式是让主线程发出通知信号,并在其中执行它们的处理。您可以安全地执行此操作,方法是让主线程使用pthread_cond_t,pthread_mutex_t对来监视计数器,并让信号处理程序使用相同的对来更新计数器并通知更改。

因此,主线程可以将信号视为在状态之间转换的简单输入,例如Normal / SIGINT - &gt;退出,退出/ SIGALRM - &gt;硬停。 Free()可能有点笨拙,因为它可能导致你的程序产生零星的内存引用,这可能被用作攻击面。