Added exercise for signal handler
This commit is contained in:
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