pthread_cond_wait在签名\u handler()后返回?
同事们 如果我向停留在pthread_cond_wait()上的线程发送SIGINT信号,当sign_handler()返回时,pthread_cond_wait()也会返回吗 如果没有,是否有任何方法使pthread_cond_wait()返回 如果我向停留在pthread_cond_wait()上的线程发送SIGINT信号,当sign_handler()返回时,pthread_cond_wait()也会返回吗 没有 如果没有,是否有任何方法使pthread_cond_wait()返回 不,你试图使用错误的工具来解决任何潜在的问题 (从技术上讲,pthread_cond_wait在签名\u handler()后返回?,c,linux,multithreading,synchronization,conditional-statements,C,Linux,Multithreading,Synchronization,Conditional Statements,同事们 如果我向停留在pthread_cond_wait()上的线程发送SIGINT信号,当sign_handler()返回时,pthread_cond_wait()也会返回吗 如果没有,是否有任何方法使pthread_cond_wait()返回 如果我向停留在pthread_cond_wait()上的线程发送SIGINT信号,当sign_handler()返回时,pthread_cond_wait()也会返回吗 没有 如果没有,是否有任何方法使pthread_cond_wait()返回 不,你
pthread\u cond\u timedwait()
允许在信号传递中断时返回,但它不会返回,至少在运行内核5.3.0的x86-64上使用GNU glibc 2.27时是这样。是的,我检查过了。)
我如何解决我的问题
让我们假设条件变量是您用例的最佳选项。(不过,这只是一个猜测;您没有告诉我们您试图解决的真正问题,只是告诉我们您选择的解决方案如何不起作用。)
然后,推荐的解决方案是使用helper线程捕获信号,如SIGINT、using或sigtimedwait()。然后,该助手线程可以在相关条件变量上设置一个特定的退出所需的volatile sig\u atomic\u标记和pthread\u cond\u signal()
或pthread\u cond\u broadcast()
,让它们知道发生了什么重要的事情。那些等待条件变量的人显然应该首先检查helper标志;如果设置了,则假设这是唤醒信号的来源。通常我将这些标志命名为“需要退出”或类似标志
这种信号处理辅助线程的关键是需要在所有线程(包括处理辅助线程本身)中阻塞信号。最好在创建任何其他线程之前在主线程中执行此操作,因为这样创建的线程将继承相同的信号掩码
siginfo_t结构包含各种有用的信息。最有用的可能是.si_pid
字段,它告诉哪个进程(或0
if内核)发送了信号。这样,如果出于内部目的使用saySIGRTMIN+0
到SIGRTMAX-0
信号,则可以忽略它们,除非它们来自进程本身(其他线程,.si_pid==getpid()
)
线程取消(延迟,在取消点;pthread_cond_wait()是取消点)是另一个选项。可以使用pthread_cleanup_push()设置/添加要在线程取消时运行的函数。这基本上是强制终止目标线程,但它可以运行在终止之前设置的任何清理函数。您还可以使用pthread_cleanup_pop()解除任何清理函数的作用——一个参数指定是运行并丢弃清理函数,还是仅丢弃清理函数。但是,当被取消时,线程总是死亡
请使用pthread\u attr\u t
将堆栈大小限制为2的合理幂。如果堆栈上没有任何大型数组或结构(局部变量),那么
#include <limits.h>
#ifndef THREAD_STACK_SIZE
#define THREAD_STACK_SIZE (4 * PTHREAD_STACK_MIN)
#endif
对于堆栈大小和阻塞所有线程中的某些信号(通过在创建其他线程的线程中首先阻塞它们;它们将继承信号掩码),应该可以正常工作
除了不能被阻止、捕获或忽略的SIGKILL
和SIGSTOP
之外,您可以向被阻止的掩码添加任何其他信号
pthread\u attr\u t
到pthread\u create()
的第二个参数只是设置(或属性)的集合,如配置;pthread_create()调用不会“使用”它们。可以多次使用同一组属性。这一个只包含所需的堆栈大小。(它不包含堆栈本身,只包含所需的大小。)
默认的堆栈大小非常大,通常为8MIB,这意味着大量虚拟内存是为线程堆栈保留的,实际上没有什么好的理由。此外,它严重限制了进程可以创建的线程数
在许多方面,拥有用于信号处理的助手线程比实际的信号处理程序更容易,因为只有在信号处理程序中才能安全使用;而在helper线程中,您可以使用all
如果我向停留在pthread_cond_wait()上的线程发送SIGINT信号,当sign_handler()返回时,pthread_cond_wait()也会返回吗
没有
如果没有,是否有任何方法使pthread_cond_wait()返回
不,你试图使用错误的工具来解决任何潜在的问题
(从技术上讲,pthread\u cond\u timedwait()
允许在信号传递中断时返回,但它不会返回,至少在运行内核5.3.0的x86-64上使用GNU glibc 2.27时是这样。是的,我检查过了。)
我如何解决我的问题
让我们假设条件变量是您用例的最佳选项。(不过,这只是一个猜测;您没有告诉我们您试图解决的真正问题,只是告诉我们您选择的解决方案如何不起作用。)
然后,推荐的解决方案是使用helper线程捕获信号,如SIGINT、using或sigtimedwait()。然后,该助手线程可以在相关条件变量上设置一个特定的退出所需的volatile sig\u atomic\u标记和pthread\u cond\u signal()
或pthread\u cond\u broadcast()
,让它们知道发生了什么重要的事情。那些等待条件变量的人显然应该首先检查helper标志;如果设置了,则假设这是唤醒信号的来源。通常我将这些标志命名为“需要退出”或类似标志
这种信号处理辅助线程的关键是需要在所有线程(包括处理辅助线程本身)中阻塞信号。最好在创建任何其他线程之前在主线程中执行此操作,就像创建的thr一样
sigset_t mask;
pthread_attr_t attrs;
int err;
/* Block SIGINT in this (and all created threads) */
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
err = pthread_sigmask(SIG_BLOCK, &mask, NULL);
if (err) {
fprintf(stderr, "Cannot block signals: %s.\n", strerror(err));
return EXIT_FAILURE;
}
/* Create stack size attribute. */
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREAD_STACK_SIZE);
/*
* Create threads, use &attrs for the second parameter.
*/
/* Optional cleanup - it's a good idea to be careful. */
pthread_attr_destroy(&attrs);