2

When you send SIGUSR1 signal (say the signal handler has been set in advance) to a program while it is executing sleep(100), the signal is caught correctly but sleep(100) is terminated just after the catch. This may mean sending a signal can forcedly terminate the internal some function.

For example, in a scientific calculation program, I would like to catch SIGUSR1 and print the progress. But what if I happen to send the signal while statements like has_error_occured = true or should_break_this_roop = true are in execution? I think this may cause unexpected behavior.

How can I use SIGUSR1 (and SIGUSR2) safely? It is known that the shell command dd print the progress when it catches SIGUSR1. Why is this safe?


Sample program (I executed 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();

}
7

You should set your signal handler using sigaction(2) instead of signal(2), and set SA_RESTART in sa_flags if you don't want it to interrupt a blocking system call.

struct sigaction sa;
sa.sa_handler = your_handler;
sa.sa_flags = SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, 0);

Or, even better than that, just handle the interrupt yourself.

If nanosleep(), etc. has returned -1, check if errno == EINTR, and print the progress and then redo the call (sleep() is just a wrapper for nanosleep() on linux). You will have to do this anyway if your program grows to something more complex — there's not much you can do safely from a signal handler — see the signal-safety(7) man page on Linux.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.