Open In App

Signals in C language

Last Updated : 14 May, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

A signal is a software-generated interrupt sent to a process by the OS when the user presses Ctrl-C or another process sends a signal to this process. There is a fixed set of signals that can be sent to a process. Signals are identified by integers value, for example, the value of SIGINT is 2.

Signal Types in C

C offers various types of interruptions, which are listed below:

Signal Name

Description

Default Behaviour

SIGABRT

Abnormal termination (abort) by the program.

Program terminates

SIGFPE

Floating-point exception (e.g., division by zero or overflow).

Program terminates

SIGILL

Illegal instruction (e.g., invalid opcode).

Program terminates

SIGINT

Interrupt signal (sent when Ctrl+C is pressed by the user).

Program terminates

SIGSEGV

Segmentation fault (invalid memory access).

Program terminates

SIGTERM

Termination signal (request to terminate the process).

Program terminates

SIGKILL

Kill signal (forceful termination of a process).

Program terminates

SIGBUS

Bus error (e.g., misaligned memory access).

Program terminates

SIGQUIT

Quit signal (similar to SIGINT but causes core dump).

Program terminates (Core dump)

SIGCHLD

Child process terminated or stopped.

No action (handled by parent)

SIGCONT

Continue a stopped process.

Process resumed

SIGTSTP

Terminal stop signal (sent by pressing Ctrl+Z).

Process Stop

OS Structures for Signals

  • Signal Delivery: The OS stores incoming signals for each process in a pending signals list (or queue). This ensures that no signals are missed, and they are delivered once the process is ready to handle them.
  • Handle Signals: A process can define signal handlers for specific signals, such as using a handler for SIGTERM to clean up before termination. The OS calls these handlers when the corresponding signal is delivered.
  • Signal Masking: Processes can mask certain signals to prevent interruptions during critical sections of code. This is managed by setting a signal mask that controls which signals are blocked.
  • Signal Stack: When a signal occurs during execution, the OS saves the context of the process and manages the execution state using a signal stack. This ensures that the process can resume after the signal handler completes.

Example

In the example below, the SIGINT (2) signal is blocked, and no signals are pending.

A signal is sent to a process by setting the corresponding bit in its pending signals integer. When the OS selects a process to run, it checks the pending and blocked signals. If no signals are pending, the process continues normally. If signals are pending but blocked, the process continues, and the signals remain pending. If any signals are pending and not blocked, the OS handles them using the process’s signal routines.

Signal Handling in C

In C, signals are handled by their default behavior, but the language also provides a way to manage them manually. This process, known as signal handling, allows us to define custom actions for specific signals. By using a signal handler function, we can control how a signal is processed, giving us flexibility in how the program responds to events like errors or interruptions.

Default Signal Handlers

There are several default signal handler functions. Each signal is associated with one of these default handler routines. The different default handler routines typically have one of the following actions:

  • Ign: Ignore the signal, i.e., do nothing just return.
  • Term: Terminate the process.
  • Cont: Unblock a stopped process.
  • Stop: Block the process.
C
#include <stdio.h> 
#include <signal.h> 
  
int main() {
    while (1) {
        printf("hello world\n"); 
    } 
    return 0; 
} 


Output

hello world   
hello world
hello world
. .
. .

Above program prints "hello world" infinitely. When the user presses Ctrl + C, the SIGINT signal is sent, and the default handler terminates the process.

User Defined Signal Handlers

A process can replace the default signal handler for almost all signals (except SIGKILL) with its own handler function. A signal handler can have any name, but it must return void and accept a single int parameter, representing the signal number.

To trigger the signal handler when the signal has occurred, we use signal() function that is provided by <signal.h> header file.

Syntax:

C
signal(type, signalHandler);

where,

  • type: Type of signal.
  • signalHandler: Function that handle type signal.

Example:

C
#include <stdio.h> 
#include <signal.h> 
#include <stdlib.h>
  
// Handler for SIGINT, triggered by 
// Ctrl-C at the keyboard 
void singalHandler(int sig)  { 
    printf("Caught signal %d\n", sig);
    exit(sig);
} 
  
int main()  { 
    signal(SIGINT, singalHandler); 
    while (1){
        printf("Hello World!\n");
    }
    return 0; 
}


Output

Hello World!
Hello World!
Hello World!
....
Ctrl+C (Enter by user)
Caught signal 2

In the above code, program prints "Hello World!" infinitely, when user enter Ctrl+C then signal method handle this signal by singalHandler function, which prints the statement with signal number "Caught signal 2".

Generate Signals Manually

In the above example, you can see that the signal is automatically generated when the user presses Ctrl+C. There are functions available that provide the functionality to generate signals manually.

raise() Function

The raise() function in C enables you to send a signal to the current process. It takes the signal type as an argument and triggers that signal within the same process.

Syntax:

C
raise(signal_type);

It returns 0 on success, or a non-zero value on failure.

Example:

C
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

// Signal handler function
void signalHandler(int sig) {
    printf("Interrupt handled: %d", sig);
    
    // Optionally exit the program after handling
    exit(sig);
}

int main() {
    
    // Handle signal
    signal(SIGINT, signalHandler);
    
    // Automatically generate a signal
    raise(SIGINT);
    return 0;
}

Output
Interrupt handled: 2

kill() Function

The kill() function allows us to send the signals to other processes or group of processes by using process id.

Syntax:

C
kill(pid, signal_type);

where,

  • pid: The process ID of the target process to which the signal should be sent.

Example:

C
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void handle_signal(int signal_num) {
    printf("Received signal: %d\n", signal_num);
}

int main() {
    
    // Handle signal
    signal(SIGINT, handle_signal);

    // Get current process ID
    pid_t pid = getpid();

    // Generate signal using kill()
    kill(pid, SIGINT);
    return 0;
}


Output

Received signal: 2

Practice Tags :

Similar Reads