向程序发送 SIGUSR1 是否安全?为什么?

向程序发送 SIGUSR1 是否安全?为什么?

当您在程序执行时向程序发送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();

}

答案1

您应该使用设置信号处理程序信号动作(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);

或者,甚至更好的是,您自己处理中断。

如果nanosleep()等返回-1,则检查是否errno == EINTR,并打印进度,然后重做调用(sleep()只是linux上nanosleep()的包装器)。如果您的程序变得更复杂,您无论如何都必须这样做 - 您无法通过信号处理程序安全地做很多事情 - 请参阅signal-safety(7) 手册页在 Linux 上。

相关内容