#include #include #include #include #include // 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; } }