我正在启动一堆可连接的工作线程,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>
答案 0 :(得分:2)
简短的回答是你做不到;但你可以做点接近。
Free(),malloc()以及通向它们的所有路径都不是信号安全的;所以你不能从信号处理程序中调用它们。这些函数很少会注意到信号(重新)进入,因此可能导致不可预测的行为。
一个好的模式是让主线程发出通知信号,并在其中执行它们的处理。您可以安全地执行此操作,方法是让主线程使用pthread_cond_t,pthread_mutex_t对来监视计数器,并让信号处理程序使用相同的对来更新计数器并通知更改。
因此,主线程可以将信号视为在状态之间转换的简单输入,例如Normal / SIGINT - &gt;退出,退出/ SIGALRM - &gt;硬停。 Free()可能有点笨拙,因为它可能导致你的程序产生零星的内存引用,这可能被用作攻击面。