【发布时间】:2018-09-04 08:30:47
【问题描述】:
我正在编写一个程序,其中子进程和父进程都可以向子进程发送 SIGTERM 信号。
信号处理程序是这样的:
void custom_signal_handler(int signum, siginfo_t* info, void* ptr) {
if (signum == SIGTERM) {
printf("1\n");
}
else if (signum == SIGCONT) {
printf("2\n");
}
}
(我已经简化了ifs 中的打印以使这里的代码更简单)。
对于SIGCONT信号 - 只有父级可以使用kill(childPid, SIGCONT) 调用此信号。发生这种情况时,孩子的信号处理程序会按预期打印“2”。
但是,对于SIGTERM 信号 - 父母可以通过发送kill(childPid, SIGTERM) 来调用它,而孩子可以通过调用raise(SIGTERM) 来调用它。问题是“1”仅在子级发出SIGTERM 信号时打印,而不是在父级调用它时打印。
我已经为孩子注册了信号处理程序:
// set up signal handler
struct sigaction custom_action;
memset(&custom_action, 0, sizeof(custom_action));
custom_action.sa_sigaction = custom_signal_handler;
custom_action.sa_flags = SA_SIGINFO;
// assign signal handlers
if (0 != sigaction(SIGCONT, &custom_action, NULL)) {
printf("Signal registration failed: %s\n",strerror(errno));
return -1;
}
if (0 != sigaction(SIGTERM, &custom_action, NULL)) {
printf("Signal registration failed: %s\n",strerror(errno));
return -1;
}
有什么想法吗?谢谢!
【问题讨论】:
-
custom_action是如何初始化的?您能尝试创建一个Minimal, Complete, and Verifiable Example 并展示给我们看吗?如果您这样做raise(SIGTERM),会发生任何事情吗?您是否检查过(可能使用调试器)根本没有调用信号处理程序?你检查过raise返回的内容吗? -
在这种情况下,你应该关心刷新输出。
-
@Someprogrammerdude 我已经编辑了问题以包含 sigaction 初始化。对于调试,我检查了
kill(childPid,SIGTERM)是否被调用。raise(SIGTERM)有效(我在问题中写过)。谢谢! -
哦,请记住
printf不是 signal-safe 函数。没有真正的 C stdio 函数。 -
@Someprogrammerdude 使用
sprintf后跟写应该是安全的 “可能是安全的”可能更准确。 Linux man page 没有提到sprintf()是异步信号安全的。例如,Solaris man page 明确声明“sprintf()和snprintf()函数是异步信号安全的。”。由于字符串是固定的,因此不需要任何*printf()函数。write( 2, "1\n", strlen( "1\n" ) );就足够了。
标签: c linux signals signal-handling sigterm