|
#define _GNU_SOURCE |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
|
#include <signal.h> |
|
#include <sys/signalfd.h> |
|
|
|
/* Signal handler for traditional signal() approach */ |
|
static void sigint_handler(int signo) |
|
{ |
|
printf("\nReceived SIGINT (signal %d)\n", signo); |
|
printf("Exiting gracefully...\n"); |
|
_exit(EXIT_SUCCESS); |
|
} |
|
|
|
static void use_signalfd(void) |
|
{ |
|
sigset_t mask; |
|
int sfd; |
|
struct signalfd_siginfo fdsi; |
|
ssize_t s; |
|
|
|
/* Block SIGINT so it won't be handled by the default signal handler */ |
|
sigemptyset(&mask); |
|
sigaddset(&mask, SIGINT); |
|
|
|
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { |
|
perror("sigprocmask"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
/* Create a signalfd for SIGINT */ |
|
sfd = signalfd(-1, &mask, 0); |
|
if (sfd == -1) { |
|
perror("signalfd"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
printf("Using signalfd mode. Waiting for SIGINT (press Ctrl+C)...\n"); |
|
|
|
/* Read from signalfd - this blocks until a signal arrives */ |
|
s = read(sfd, &fdsi, sizeof(fdsi)); |
|
if (s != sizeof(fdsi)) { |
|
perror("read"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
/* Handle the signal */ |
|
if (fdsi.ssi_signo == SIGINT) { |
|
printf("\nReceived SIGINT (signal %d)\n", fdsi.ssi_signo); |
|
printf("Sent by PID: %d, UID: %d\n", fdsi.ssi_pid, fdsi.ssi_uid); |
|
printf("Exiting gracefully...\n"); |
|
} |
|
|
|
close(sfd); |
|
} |
|
|
|
static void use_signal(void) |
|
{ |
|
/* Register the signal handler */ |
|
if (signal(SIGINT, sigint_handler) == SIG_ERR) { |
|
perror("signal"); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
printf("Using signal mode. Waiting for SIGINT (press Ctrl+C)...\n"); |
|
|
|
/* Wait indefinitely for the signal */ |
|
while (1) { |
|
pause(); |
|
} |
|
} |
|
|
|
int main(int argc, char *argv[]) |
|
{ |
|
if (argc != 2) { |
|
fprintf(stderr, "Usage: %s <signalfd|signal>\n", argv[0]); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
if (strcmp(argv[1], "signalfd") == 0) { |
|
use_signalfd(); |
|
} else if (strcmp(argv[1], "signal") == 0) { |
|
use_signal(); |
|
} else { |
|
fprintf(stderr, "Invalid argument: %s\n", argv[1]); |
|
fprintf(stderr, "Usage: %s <signalfd|signal>\n", argv[0]); |
|
exit(EXIT_FAILURE); |
|
} |
|
|
|
return EXIT_SUCCESS; |
|
} |
|
|