man*_*nav 3 c linux posix signals pthreads
我在 Linux 中有一个“C”应用程序,其中我注册了 SIGALRM 处理程序。我的 SIGALRM 处理程序更新其他线程也在访问的一些全局数据。要求:为了保护全局数据,我需要在线程内访问信号时完全阻止信号。所以我需要一种方法来实现它。问题:我无法完全阻止信号。sigprocmask 不工作。尽管如果 main 是唯一正在运行的线程,它会阻塞信号。但是当多个线程运行时,SIGALRM 不断出现。我已经测试了 pthread_sigmask 但仅更新当前线程的信号掩码。
添加代码逻辑:
sig_atomic_t atm_var;
void signal_handler()
{
atm_var++;
}
void thread_func()
{
pthread_sigmask(UNBLOCK,...);
while(1)
{
/* some stuff */
pthread_sigmask(BLOCK,...);
/* critical section, can easily access or modify atm_var */
pthread_sigmask(UNBLOCK,...);
}
}
int main()
{
sigprocmask(BLOCK,...);
pthread_create(...,thread_func,...);
sigaction(SIGALRM,...);
setitimer(ITIMER_REAL,...);
while(1)
{
}
}
Run Code Online (Sandbox Code Playgroud)
再补充一点:在主线程或其他线程中修改 sig_atomic_t 变量(信号处理程序正在修改)有多安全?
或者
当我修改主线程或其他线程内的 sig_atomic_t 变量时,不阻止信号是安全的做法吗?
您的问题是各种信号可以针对整个进程或特定线程。当针对整个进程时,它们将被传递到任何没有阻塞它们的线程。
man (7) signal
进程控制的信号可以被传递到当前没有阻止该信号的任何一个线程。如果多个线程的信号未被阻塞,则内核会选择任意一个线程来向其传递信号。
因为信号掩码是由每个线程从创建它们的任何线程继承的,所以一种相当标准的技术是在创建者中阻止它们(为简单起见,我们假设这是主线程),然后让每个生成的线程适当地取消阻止信号。
对此的一种常见变化是在主线程中阻止它们,并让它们在除一个之外的所有生成线程中保持阻塞。该线程解除对信号的阻塞,并且所有进程定向信号都针对它进行处理。
以上可能就是您想要做的。您可能在运行信号处理程序的线程中正确阻止了 SIGALRM。不幸的是,这不会阻止 SIGALRM 被传递到第二个线程。