【发布时间】:2020-03-21 06:51:27
【问题描述】:
我发现以下代码在 macOS 和 Linux 中的工作方式不同:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
void catcher( int sig ) {
printf( "Signal catcher called for signal %d\n", sig );
}
int main( int argc, char *argv[] )
{
struct sigaction sigact;
sigset_t waitset;
int sig;
int result = 0;
sigemptyset( &sigact.sa_mask );
sigact.sa_flags = 0;
sigact.sa_handler = catcher;
sigaction( SIGINT, &sigact, NULL );
sigemptyset( &waitset );
sigaddset( &waitset, SIGHUP);
result = sigwait(&waitset, &sig) ;
if(result == 0)
{
printf( "sigwait() returned for signal %d\n", sig );
}
}
当在 macOS 上运行并将 SIGINT 发送到进程时,其处理程序仅在发送 SIGHUP 后执行(从而导致 sigwait() 返回)。换句话说,它看起来 sigwait() 在其等待期间阻塞了其等待掩码之外的所有信号。当同一个程序在 Linux 上运行时,只要将 SIGINT 发送到进程,就会传递 SIGINT,即运行处理程序。因此它在 Linux 中看起来 sigwait() 不会阻塞其等待掩码之外的信号。 哪个是标准行为? SUSv3 没有说清楚。
【问题讨论】:
-
我可以请您在调用
sigwait之前先#include <signal.h>和SIG_BLOCK 该SIGINT 吗? (两者都不会从您识别的陌生感中减去。) -
显然
signal.h被包含(该行只是在副本中滑落,否则不会编译)。添加 SIGINT 块可以在 macOS 中按预期工作。也就是说,SIGINT 被阻塞,在 SIGHUP 之后,程序定期退出。 -
对不起,我打错了后半部分——我的意思是 SIG_BLOCK 那个 SIGHUP。对非阻塞信号使用
sigwait是明确未定义的。 -
我不确定是否理解:SUS 说“set 定义的信号在调用 sigwait() 时应已被阻塞;否则,行为未定义。”这里提出的问题是信号 not 在传递给 sigwait() 的集合中。
标签: c macos linux-kernel signals sus