operating-systems/lab1/v7/using_signal_handlers.c

117 lines
3.5 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
// Global variable with data, needed to communicate with another process.
struct ping_pong_data_t {
char const *name;
pid_t pid_to_print;
pid_t pid_to_send;
double delay_seconds;
} ping_pong_data;
// Signal handler for printing PID and sending signal back to another process.
void do_ping_pong(int signo) {
if (signo != SIGUSR1) // Protecting from unexpected signals
return;
// Printing some useful info
printf("[%s] Got signal\n", ping_pong_data.name);
printf("[%s] Another side PID=%d\n", ping_pong_data.name, ping_pong_data.pid_to_print);
// Sleeping to avoid unreadable spam
printf("[%s] Sleeping %lf seconds before sending signal\n", ping_pong_data.name, ping_pong_data.delay_seconds);
usleep((useconds_t) (1000 * 1000 * ping_pong_data.delay_seconds));
// Sending signal back
printf("[%s] Sending signal\n", ping_pong_data.name);
kill(ping_pong_data.pid_to_send, SIGUSR1);
}
// Global flag to stop infinite loop on interrupt (Ctrl+C)
volatile int is_running = 1;
// Interrupt (Ctrl+C) handler
void interrupt(int signo) {
if (signo != SIGINT) // Protecting from unexpected signals
return;
kill(ping_pong_data.pid_to_send, SIGINT);
is_running = 0;
}
// Entry point
int main(void) {
// Obtaining PID of parent (main) process
pid_t parent_pid = getpid();
// Obtaining PID of child (forked) process
pid_t child_pid = fork();
switch (child_pid) {
case -1:
perror("Failed to fork\n");
return EXIT_FAILURE;
case 0:
// Obtaining PID of child (forked) process because fork() didn't return it
child_pid = getpid();
// Initializing settings
ping_pong_data.name = "\033[36mchild\033[0m";
ping_pong_data.delay_seconds = 1.5;
ping_pong_data.pid_to_print = parent_pid;
ping_pong_data.pid_to_send = parent_pid;
// Debug info printing
printf("[%s] My PID=%d\n", ping_pong_data.name, getpid());
// Initializing interruption (Ctrl+C) handler
signal(SIGINT, interrupt);
// Initializing communication handler
signal(SIGUSR1, do_ping_pong);
// Eventloop
while (is_running)
pause();
// Notification about execution finishing
printf("[%s] Interrupted\n", ping_pong_data.name);
return EXIT_SUCCESS;
default:
// Initializing settings
ping_pong_data.name = "\033[31mparent\033[0m";
ping_pong_data.delay_seconds = 1.5;
ping_pong_data.pid_to_print = child_pid;
ping_pong_data.pid_to_send = child_pid;
// Debug info printing
printf("[%s] My PID=%d\n", ping_pong_data.name, getpid());
// Initializing interruption (Ctrl+C) handler
signal(SIGINT, interrupt);
// Initializing communication handler
signal(SIGUSR1, do_ping_pong);
// Sending initial signal to start communication chain
kill(parent_pid, SIGUSR1);
// Eventloop
while (is_running)
pause();
// Notification about execution finishing
printf("[%s] Interrupted\n", ping_pong_data.name);
// Releasing zombie-process
waitpid(child_pid, NULL, 0);
return EXIT_SUCCESS;
}
}