Describe the purpose of the sigprocmask function in Linux signal handling. Explain the different ways it can modify the signal mask and provide an example of its usage to block SIGINT.
The sigprocmask is the function which is used to change the signal mask of the calling process. The signal mask determines which processes are currently blocked from being delivered. It can be understood using the following example:-
#include stdio.h #include stdlib.h #include signal.h #include unistd.h void handle_signal(int sig) { printf("Caught signal %d\n", sig); } int main() { struct sigaction sa; sa.sa_handler = handle_signal; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); // Set up the signal handler for SIGINT if (sigaction(SIGINT, &sa, NULL) == -1) { perror("sigaction"); exit(EXIT_FAILURE); } sigset_t mask, oldmask, pending; // Initialize the signal set to empty sigemptyset(&mask); // Add SIGINT to the signal set sigaddset(&mask, SIGINT); // Block SIGINT and save the old signal mask if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) { perror("sigprocmask"); exit(EXIT_FAILURE); } printf("SIGINT blocked. Press Ctrl+C...\n"); sleep(5); // SIGINT is blocked during this sleep // Check for pending signals if (sigpending(&pending) == -1) { perror("sigpending"); exit(EXIT_FAILURE); } // Test if SIGINT is pending if (sigismember(&pending, SIGINT)) { printf("SIGINT is pending\n"); } else { printf("SIGINT is not pending\n"); } // Restore the old signal mask, unblocking SIGINT if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) { perror("sigprocmask"); exit(EXIT_FAILURE); } printf("SIGINT unblocked. Press Ctrl+C again...\n"); // Loop indefinitely while (1) { printf("Running...\n"); sleep(1); } return 0; }
Here the sigprocmask initially blocks SIGINT
Then the program sleeps for 5 secs while SIGINT is blocked.
The sigpending function checks for the pending signals and SIGINT is blocked.
sigprocmask changes the mask to old mask and SIGINT is unblocked and sent to the process.