将 SIGUSR1 发送到程序是否安全,为什么?

ynn*_*ynn 2 c signals c++

当您SIGUSR1在程序执行时向程序发送信号(假设信号处理程序已预先设置)时sleep(100),信号会被正确捕获,但sleep(100)会在捕获后立即终止。这可能意味着发送信号可以强制终止内部某些功能。

例如,在一个科学计算程序中,我想捕捉SIGUSR1并打印进度。但是如果我碰巧在像has_error_occured = trueshould_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)

qub*_*ert 7

你应该设置使用信号处理程序的sigaction(2)代替信号(2) ,并设置SA_RESTARTsa_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) 手册页