Added exercise for signal handler

This commit is contained in:
Fabio Scotto di Santolo
2025-08-22 16:02:54 +02:00
parent 035027ad06
commit 331308b2d8
4 changed files with 140 additions and 0 deletions

View File

@@ -75,6 +75,21 @@ This is an organized list of all exercises completed so far, including a brief d
--- ---
## 🚦 signal_handler
**Description**: A C program demonstrating robust signal handling for `SIGINT` and `SIGUSR1` using `sigaction` with `SA_SIGINFO`.
- 📄 [README](signal_handler/README.md)
- 📂 Directory: `signal_handler/`
- ✅ Features:
- Handles `SIGINT` up to three times before exiting
- Handles `SIGUSR1` with a simple message
- Masks signals during handler execution to avoid reentrancy issues
- Includes comments and clear separation of handler logic
- Makefile included with standard targets
---
## 🔧 Tooling & Automation ## 🔧 Tooling & Automation
**Shared tools and scripts used across projects**: **Shared tools and scripts used across projects**:

View File

@@ -0,0 +1,12 @@
CC = gcc
CFLAGS = -Wall -Wextra -O2
TARGET = signal_handler
SRC = main.c
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) -o $(TARGET) $(SRC)
clean:
rm -f $(TARGET)

View File

@@ -0,0 +1,55 @@
# Signal Handler
## Overview
This project demonstrates how to handle UNIX signals in C using `sigaction`.
It specifically intercepts **SIGINT** and **SIGUSR1** and prints messages when these signals are received.
---
## Features
- Intercepts **SIGINT** (usually generated with `Ctrl + C`) and **SIGUSR1**`.
- Prints a custom message for each signal.
- Tracks the number of `SIGINT` signals received and terminates after a defined count.
- Demonstrates proper use of:
- `sigaction()` instead of `signal()` for consistent behavior.
- `volatile sig_atomic_t` for safe signal state handling.
---
## Build
```bash
make
```
---
## Run
```bash
./signal_handler
```
---
## Test
- Open another terminal and run:
```bash
kill -USR1 <PID>
```
where `<PID>` is the process ID of `signal_handler`.
- Press `Ctrl + C` in the terminal running the program to send `SIGINT`.
---
## Clean
```bash
make clean
```

View File

@@ -0,0 +1,58 @@
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
volatile sig_atomic_t sigint_caught = 0;
void signal_handler(int signo, siginfo_t *si, void *ucontext)
{
(void)si;
(void)ucontext;
if (signo == SIGINT) {
sigint_caught += 1;
if (write(STDOUT_FILENO, "Caught SIGINT signal\n", 22) == -1) {
_exit(EXIT_FAILURE);
}
if (sigint_caught >= 3) {
if (write(STDOUT_FILENO, "Reach SIGINT limit\n", 20) ==
-1) {
_exit(EXIT_FAILURE);
}
_exit(EXIT_FAILURE);
}
} else if (signo == SIGUSR1) {
if (write(STDOUT_FILENO, "Caught SIGUSR1 signal\n", 23) == -1) {
_exit(EXIT_FAILURE);
}
} else {
if (write(STDOUT_FILENO, "Unknown signal\n", 16) == -1) {
_exit(EXIT_FAILURE);
}
}
}
int main(void)
{
struct sigaction action;
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, SIGINT);
sigaddset(&action.sa_mask, SIGUSR1);
action.sa_sigaction = signal_handler;
action.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &action, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
if (sigaction(SIGUSR1, &action, NULL) == -1) {
perror("sigaction");
exit(EXIT_FAILURE);
}
printf("Hi, I'm process with PID %d\n", getpid());
for (;;)
pause();
return EXIT_SUCCESS;
}