当您SIGUSR1
在程序执行时向程序发送信号(假设信号处理程序已预先设置)时sleep(100)
,信号会被正确捕获,但sleep(100)
会在捕获后立即终止。这可能意味着发送信号可以强制终止内部某些功能。
例如,在一个科学计算程序中,我想捕捉SIGUSR1
并打印进度。但是如果我碰巧在像has_error_occured = true
或should_break_this_roop = true
正在执行这样的语句时发送信号怎么办?我认为这可能会导致意外行为。
我怎样才能安全地使用SIGUSR1
(和SIGUSR2
)?众所周知,shell 命令dd
在捕获SIGUSR1
. 为什么这是安全的?
示例程序(我执行kill -SIGUSR1 xxxxx
):
#include <iostream>
#include <csignal>
#include <unistd.h>
void my_handler(int signal) {
; //some instructions
}
void just_sleep() {
std::cout << "sleep() starts.\n";
sleep(100); //not wait for 100s if a signal caught
std::cout << "sleep() ends.\n"; //executed even if a signal caught
}
int main() {
signal(SIGUSR1, my_handler);
just_sleep();
}
Run Code Online (Sandbox Code Playgroud)
你应该设置使用信号处理程序的sigaction(2)代替信号(2) ,并设置SA_RESTART
在sa_flags
,如果你不希望它中断阻塞的系统调用。
struct sigaction sa;
sa.sa_handler = your_handler;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, 0);
Run Code Online (Sandbox Code Playgroud)
或者,甚至比这更好,自己处理中断。
如果 nanosleep() 等返回 -1,请检查是否errno == EINTR
,并打印进度,然后重做调用(sleep() 只是 linux 上 nanosleep() 的包装器)。如果您的程序变得更复杂,您无论如何都必须这样做——从信号处理程序中您可以安全地做的事情并不多——请参阅Linux 上的 signal-safety(7) 手册页。