Signal Handling
Signals in Linux are a fundamental mechanism for handling asynchronous events. A signal is a limited form of inter-process communication used to notify a process that a specific event has occurred. Signals can be sent by the kernel or by other processes, and are often used for events such as segmentation faults (SIGSEGV), illegal instructions (SIGILL), or external interrupts like pressing Ctrl+C in a terminal (SIGINT).
When a signal is delivered to a process, the process can respond in one of several ways: it can ignore the signal, use the default action (such as terminating the process), or catch the signal by installing a custom signal handler. Signal handlers are functions written in C that execute in response to specific signals, allowing you to perform cleanup, log information, or otherwise manage the event before the process continues or terminates.
Signal handling is crucial for building robust Linux programs. For example, you might want your program to clean up temporary files or save state before exiting when interrupted by a user. To do this, you must understand how to register signal handlers and ensure your code is safe to execute in the asynchronous context of a signal.
signal_handler_demo.c
12345678910111213141516171819202122232425262728293031#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void handle_sigint(int sig) { // Print a message when SIGINT is received write(STDOUT_FILENO, "Caught SIGINT! Exiting gracefully.\n", 34); _exit(0); // Use _exit() to avoid unsafe operations in handler } int main() { // Register handle_sigint as the handler for SIGINT (Ctrl+C) struct sigaction sa; sa.sa_handler = handle_sigint; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGINT, &sa, NULL) == -1) { perror("sigaction"); return 1; } printf("Running. Press Ctrl+C to trigger SIGINT...\n"); // Loop forever, waiting for signals while (1) { pause(); // Wait for a signal to arrive } return 0; }
In the provided program, you install a custom signal handler for SIGINT (triggered by pressing Ctrl+C). The handler function, handle_sigint, uses the write system call to print a message, then calls _exit(0) to terminate the process immediately. This approach avoids calling functions that are not safe within a signal handler.
When a signal handler is invoked, it interrupts the normal flow of your program at an unpredictable point. This raises concerns about reentrancy—if your handler calls functions that are not reentrant (that is, not safe to be interrupted and called again before a previous invocation is complete), you may encounter undefined behavior or data corruption. For this reason, only a small set of system calls and library functions are considered signal-safe; these include _exit, write, and a few others.
Best practices for writing signal handlers in C include:
- Keep the handler as short and simple as possible;
- Avoid calling non-reentrant or unsafe functions such as
printf,malloc, or most standard library functions; - Use only async-signal-safe functions within the handler;
- If complex cleanup or communication is needed, set a flag in the handler and perform the work in the main program flow.
By following these guidelines, you ensure your program responds to signals reliably and safely, minimizing the risk of subtle bugs or crashes.
Grazie per i tuoi commenti!
Chieda ad AI
Chieda ad AI
Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione
Fantastico!
Completion tasso migliorato a 7.69
Signal Handling
Scorri per mostrare il menu
Signals in Linux are a fundamental mechanism for handling asynchronous events. A signal is a limited form of inter-process communication used to notify a process that a specific event has occurred. Signals can be sent by the kernel or by other processes, and are often used for events such as segmentation faults (SIGSEGV), illegal instructions (SIGILL), or external interrupts like pressing Ctrl+C in a terminal (SIGINT).
When a signal is delivered to a process, the process can respond in one of several ways: it can ignore the signal, use the default action (such as terminating the process), or catch the signal by installing a custom signal handler. Signal handlers are functions written in C that execute in response to specific signals, allowing you to perform cleanup, log information, or otherwise manage the event before the process continues or terminates.
Signal handling is crucial for building robust Linux programs. For example, you might want your program to clean up temporary files or save state before exiting when interrupted by a user. To do this, you must understand how to register signal handlers and ensure your code is safe to execute in the asynchronous context of a signal.
signal_handler_demo.c
12345678910111213141516171819202122232425262728293031#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> void handle_sigint(int sig) { // Print a message when SIGINT is received write(STDOUT_FILENO, "Caught SIGINT! Exiting gracefully.\n", 34); _exit(0); // Use _exit() to avoid unsafe operations in handler } int main() { // Register handle_sigint as the handler for SIGINT (Ctrl+C) struct sigaction sa; sa.sa_handler = handle_sigint; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); if (sigaction(SIGINT, &sa, NULL) == -1) { perror("sigaction"); return 1; } printf("Running. Press Ctrl+C to trigger SIGINT...\n"); // Loop forever, waiting for signals while (1) { pause(); // Wait for a signal to arrive } return 0; }
In the provided program, you install a custom signal handler for SIGINT (triggered by pressing Ctrl+C). The handler function, handle_sigint, uses the write system call to print a message, then calls _exit(0) to terminate the process immediately. This approach avoids calling functions that are not safe within a signal handler.
When a signal handler is invoked, it interrupts the normal flow of your program at an unpredictable point. This raises concerns about reentrancy—if your handler calls functions that are not reentrant (that is, not safe to be interrupted and called again before a previous invocation is complete), you may encounter undefined behavior or data corruption. For this reason, only a small set of system calls and library functions are considered signal-safe; these include _exit, write, and a few others.
Best practices for writing signal handlers in C include:
- Keep the handler as short and simple as possible;
- Avoid calling non-reentrant or unsafe functions such as
printf,malloc, or most standard library functions; - Use only async-signal-safe functions within the handler;
- If complex cleanup or communication is needed, set a flag in the handler and perform the work in the main program flow.
By following these guidelines, you ensure your program responds to signals reliably and safely, minimizing the risk of subtle bugs or crashes.
Grazie per i tuoi commenti!