YouTip LogoYouTip

C Function Sigwait

# C Library Function - sigwait() The `sigwait()` function is a standard C library function used to synchronously wait for signals. Instead of handling signals asynchronously using a signal handler, `sigwait()` suspends the calling thread until one of the signals specified in a signal set becomes pending. It then removes that signal from the pending queue and returns its number. This function is defined in the `` header file and is highly recommended for multi-threaded programming (POSIX threads) to handle signals synchronously and avoid the complexities of asynchronous signal handlers. --- ## Syntax ```c #include int sigwait(const sigset_t *set, int *sig); ``` ### Parameters * **`const sigset_t *set`**: A pointer to a `sigset_t` signal set that specifies the signals the thread is waiting for. * **`int *sig`**: A pointer to an integer variable where the function will store the number of the signal that was caught. ### Return Value * **On success**: Returns `0`, and the number of the received signal is stored in the memory pointed to by `sig`. * **On failure**: Returns a positive error number (e.g., `EINVAL` if the signal set contains invalid signals). Unlike many other system calls, `sigwait()` does not set `errno`; it returns the error code directly. --- ## Code Example The following program demonstrates how to use `sigwait()` to synchronously wait for the `SIGINT` (Ctrl+C) signal in a dedicated thread. To ensure `sigwait()` works correctly, the target signals must be blocked in all threads (including the main thread) before spawning the waiting thread. This prevents the default signal action (such as terminating the program) from triggering. ```c #include #include #include #include #include // Thread function that synchronously waits for the SIGINT signal void* wait_for_signal(void* arg) { sigset_t *set = (sigset_t *)arg; int sig; printf("Thread waiting for signal...\n"); // sigwait blocks until one of the signals in 'set' is delivered if (sigwait(set, &sig) == 0) { printf("\nCaught signal %d: %s\n", sig, strsignal(sig)); } else { perror("sigwait failed"); } return NULL; } int main() { pthread_t thread; sigset_t set; // Initialize the signal set and add SIGINT to it sigemptyset(&set); sigaddset(&set, SIGINT); // Block SIGINT in the main thread. // Since new threads inherit the signal mask, it will be blocked there too. pthread_sigmask(SIG_BLOCK, &set, NULL); // Create a dedicated thread to wait for and handle the SIGINT signal if (pthread_create(&thread, NULL, wait_for_signal, (void*)&set) != 0) { perror("Failed to create thread"); return 1; } // The main thread continues running in a loop while (1) { printf("Main thread running... Press Ctrl+C to send SIGINT\n"); sleep(1); } // Wait for the helper thread to finish (unreachable in this infinite loop example) pthread_join(thread, NULL); return 0; } ``` ### Expected Output When you compile and run the program, and then press `Ctrl+C` on your keyboard, the output will look like this: ```text Main thread running... Press Ctrl+C to send SIGINT Main thread running... Press Ctrl+C to send SIGINT Thread waiting for signal... Main thread running... Press Ctrl+C to send SIGINT ^C Caught signal 2: Interrupt Main thread running... Press Ctrl+C to send SIGINT Main thread running... Press Ctrl+C to send SIGINT ``` --- ## Detailed Explanation 1. **`sigemptyset(&set);`**: Initializes the signal set to be empty. 2. **`sigaddset(&set, SIGINT);`**: Adds the `SIGINT` signal (typically triggered by Ctrl+C) to the signal set. 3. **`pthread_sigmask(SIG_BLOCK, &set, NULL);`**: Blocks `SIGINT` in the main thread. This is a crucial step. If the signal is not blocked, the operating system will execute the default action for `SIGINT` (which terminates the process) before `sigwait()` has a chance to consume it. 4. **`pthread_create(...)`**: Spawns a helper thread. This thread inherits the signal mask of the main thread, meaning `SIGINT` is blocked here as well. 5. **`sigwait(set, &sig);`**: The helper thread calls `sigwait()`. This function temporarily unblocks the signals in `set` for the calling thread and suspends it until one of those signals arrives. Once the signal is delivered, it is cleared from the pending queue, and `sigwait()` returns. --- ## Key Considerations * **Signals Must Be Blocked**: For `sigwait()` to work reliably, the signals you are waiting for **must be blocked** in all threads of the process. If a signal is not blocked, its delivery behavior is undefined, and it will likely trigger the default signal handler (terminating your program) or run an asynchronous signal handler instead of returning via `sigwait()`. * **No Asynchronous Handler Overhead**: By using `sigwait()`, you avoid the strict limitations of asynchronous signal handlers (where you can only safely call async-signal-safe functions like `write()`). Inside the thread after `sigwait()` returns, you can safely call any standard library function, such as `printf()`, `malloc()`, or perform complex thread synchronization. * **Multi-threaded Safety**: In multi-threaded applications, using a dedicated signal-handling thread with `sigwait()` is the industry-standard pattern for managing signals cleanly and avoiding race conditions.
← C Function Timespec_GetC Function Psignal β†’