/* signaltester, catch & print signals * This is used for testing out sb2-monitor. * * Copyright (c) 2008 Nokia Corporation. All rights reserved. * Author: Lauri T. Aarnio * Licensed under LGPL version 2.1, see top level LICENSE file for details. */ #include #include #include #include #include #include #define _GNU_SOURCE /* to get strsignal(), a non-standard extension */ #include static int signals_received = 0; static void signal_handler(int sig, siginfo_t *info, void *ptr) { (void)ptr; /* unused param */ signals_received++; fprintf(stderr, "\nGot signal %d (%s), received %d signals\n", sig, strsignal(sig), signals_received); switch (sig) { case SIGILL: case SIGFPE: case SIGSEGV: if ((info->si_code != SI_USER) && (info->si_code != SI_QUEUE)) { /* the signal is a real, fatal, deadly * that must not be ignored. */ fprintf(stderr, "Deadly signal\n"); exit(249); } /* else it is user-generated signal */ break; case SIGTSTP: /* Job control.. stop request from tty */ fprintf(stderr, "Stopping myself.\n"); raise(SIGSTOP); return; } if (info->si_code == SI_QUEUE) { fprintf(stderr, "SI_QUEUE int=%d ptr=0x%x\n", info->si_value.sival_int, (int)(info->si_value.sival_ptr)); } else if (info->si_code == SI_USER) { fprintf(stderr, "SI_USER\n"); } else { fprintf(stderr, "si_code is %d\n", info->si_code); } } static void initialize_signal_handler(int sig) { struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_sigaction = signal_handler; act.sa_flags = SA_SIGINFO; /* block all other signals while this signal is being processed */ sigfillset(&act.sa_mask); sigaction(sig, &act, NULL); } /* Set up a signal handler for all signals that can be caught. */ static void catch_all_signals(void) { /* order here tries to follows the numerical order of signals * on Linux (see signal(7)) and Mac OS X (see signal(2)) */ initialize_signal_handler(SIGHUP); /* 1 */ initialize_signal_handler(SIGINT); initialize_signal_handler(SIGQUIT); initialize_signal_handler(SIGILL); initialize_signal_handler(SIGTRAP); /* 5 */ initialize_signal_handler(SIGABRT); #ifdef SIGIOT /* old name for SIGABRT */ initialize_signal_handler(SIGIOT); #endif #ifdef SIGEMT initialize_signal_handler(SIGEMT); #endif initialize_signal_handler(SIGFPE); /* SIGKILL, 9, cannot be caught or ignored */ initialize_signal_handler(SIGBUS); initialize_signal_handler(SIGSEGV); /* 11 */ initialize_signal_handler(SIGSYS); initialize_signal_handler(SIGPIPE); initialize_signal_handler(SIGALRM); initialize_signal_handler(SIGTERM); /* 15 */ initialize_signal_handler(SIGURG); /* SIGSTOP, 17, cannot be caught or ignored */ initialize_signal_handler(SIGTSTP); initialize_signal_handler(SIGCONT); initialize_signal_handler(SIGCHLD); /* 20 */ initialize_signal_handler(SIGTTIN); initialize_signal_handler(SIGTTOU); initialize_signal_handler(SIGIO); initialize_signal_handler(SIGXCPU); initialize_signal_handler(SIGXFSZ); /* 25 */ initialize_signal_handler(SIGVTALRM); initialize_signal_handler(SIGPROF); initialize_signal_handler(SIGWINCH); #ifdef SIGPWR initialize_signal_handler(SIGPWR); #endif #ifdef SIGLOST initialize_signal_handler(SIGLOST); #endif #ifdef SIGINFO initialize_signal_handler(SIGINFO); #endif initialize_signal_handler(SIGUSR1); initialize_signal_handler(SIGUSR2); #ifdef SIGTHR initialize_signal_handler(SIGTHR); #endif } int main(int argc, char *argv[]) { char *progname = argv[0]; int num_signals_to_receive = 10; int opt; while ((opt = getopt(argc, argv, "n:g")) != -1) { switch (opt) { case 'n': num_signals_to_receive = atoi(optarg); break; case 'g': setpgrp(); break; } } /* check parameters */ if (optind < argc) { fprintf(stderr, "Wrong number of parameters"); exit(1); } fprintf(stderr, "\n%s: PID=%d PGID=%d: waiting for %d signals\n", progname, (int)getpid(), (int)getpgrp(), num_signals_to_receive); catch_all_signals(); /* all initializations done, wait until the child has finished. */ while (signals_received < num_signals_to_receive) { if (sleep(5)) fprintf(stderr, "S"); else fprintf(stderr, "."); } return(0); }