Added exercise for signal handler
This commit is contained in:
@@ -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**:
|
||||||
|
|||||||
12
exercises/signal_handler/Makefile
Normal file
12
exercises/signal_handler/Makefile
Normal 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)
|
||||||
55
exercises/signal_handler/README.md
Normal file
55
exercises/signal_handler/README.md
Normal 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
|
||||||
|
```
|
||||||
58
exercises/signal_handler/main.c
Normal file
58
exercises/signal_handler/main.c
Normal 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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user