为何进程处理已阻塞信号?SIGINT阻塞代码的技术疑问
问题分析与解决
嘿,你对信号阻塞的理解其实是对的——阻塞的信号会被内核挂起,不会递送到进程处理,直到你解除阻塞。但你的代码里有个致命的野指针错误,导致你根本没成功阻塞SIGINT,这才是按下Ctrl+C后依然触发handler的原因。
代码里的核心问题
看这段代码:
sigset_t *ss; sigemptyset(ss); sigaddset(ss, SIGINT);
这里你只声明了一个sigset_t类型的指针ss,但没有给它分配任何有效的内存空间,也没有让它指向一个实际存在的sigset_t变量。sigemptyset和sigaddset函数需要的是一个合法的sigset_t对象的地址,操作野指针会触发未定义行为——可能会破坏进程的内存,也可能完全没修改到预期的信号集,导致后续的sigprocmask调用根本没起到阻塞SIGINT的作用。
修正后的代码
把指针改成栈上的sigset_t变量,再传递它的地址给相关函数:
void handler(int signum){ printf("handling %d\n", signum); } int main() { signal(SIGINT, handler); sigset_t ss; // 声明一个实际的sigset_t变量 sigemptyset(&ss); // 传递变量的地址 sigaddset(&ss, SIGINT); sigprocmask(SIG_BLOCK, &ss, NULL); for(;;); return 0; }
验证效果
运行修正后的程序,按下Ctrl+C,你会发现终端没有输出任何内容——这符合你的预期,因为SIGINT已经被成功阻塞,信号处于pending状态,不会被递送到进程处理。如果之后你调用sigprocmask(SIG_UNBLOCK, &ss, NULL)解除阻塞,内核就会立刻递送这个pending的SIGINT,触发handler输出内容。
内容的提问来源于stack exchange,提问作者user4180854
相关产品推荐
相关产品推荐

