想象一下用C编写的以下程序:
void handler(int signo) {
write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
signal(SIGUSR1, handler);
kill(getpid(), SIGUSR1);
write(STDOUT_FILENO, "after kill\n", 11);
}
如果我在Linux中运行此程序,输出是否可能如下:
after kill
handler
我尝试了很多次,但上面的结果并没有出现。
答案 0 :(得分:1)
如果在puts("looping");
语句之后将SIGINT信号传递给进程,则它将打印字符串" handler1"在handle1
函数中。当kill
函数返回时,输出取决于SIGUSR1信号何时传递给进程。我认为您可以使用sigsuspend
功能来确保它符合您的要求。顺便说一下,在kill
函数返回之前,至少有一个未阻塞的信号被传递给进程。
以下代码输出您想要的内容,您需要先阻止SIGUSR1信号。
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int signo) {
write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
sigset_t newmask, oldmask;
sigemptyset( &newmask );
sigaddset( &newmask, SIGUSR1 );
signal(SIGUSR1, handler);
// block the SIGUSR1 signal
sigprocmask ( SIG_BLOCK, &newmask, &oldmask );
kill(getpid(), SIGUSR1);
write(STDOUT_FILENO, "after kill\n", 11);
// reset the signal mask
sigprocmask ( SIG_SETMASK, &oldmask, NULL );
}
答案 1 :(得分:0)
puts
内部信号处理程序不好。阅读signal(7),puts
不 async-signal-safe。您应该在信号处理程序(不是puts
)中使用write(2)。
您已修改问题以使用write
代替puts
如果你坚持错误地使用puts
,你至少应该致电fflush
。但是在信号处理程序中两者都是错误的。
(不要忘记缓存了stdout
)
kill(2)
- s信号的同一个线程中运行)在返回{{1}之后调用信号处理程序}}
我不确定你是否能保证单线程进程的信号处理程序在kill
之前返回,即使我相信大多数Linux内核都会发生这种情况。你应该确定的是信号处理程序最终会被调用(但是 时你无法确定)。此外,允许内核丢失一些信号(例如,如果外部事物或进程正在发送大量相同的信号)。所谓的POSIX real-time信号是例外,而不是常态(另见this)
如果你有一个event loop(例如大约poll(2))并接受拥有特定于Linux的代码 您可以考虑使用signalfd(2)并在事件循环中对其进行轮询。