#include #include #include #include #include #include #include #include #include #include "signals.h" static void catch_loop (int); /* Convert the short signal name (NNN part of SIGNNN) to its number. Consult /usr/include/asm/signal.h for the number mappings. For this lab, hard-code the numbers; do not use the numeric constants. Return -1 if the name isn't one you need to look up. */ int signal_lookup (char *name) { // TODO: Look up the numbers for INT, SEGV, KILL, and TSTP if (strcmp (name, "INT") == 0) return 2; if (strcmp (name, "SEGV") == 0) return 11; if (strcmp (name, "KILL") == 0) return 9; if (strcmp (name, "TSTP") == 0) return 20; return -1; } // Entry point for overriding a signal handler in this lab. void override (char *signal) { int sig = signal_lookup (signal); if (sig == SIGKILL) printf ("Received bad signal name: %s\n", signal); else catch_loop (sig); } // Generic signal handler. This function doesn't use the signal number // in the provided distribution. void sig_handler (int signum __attribute__ ((unused))) { // TODO: Complete this signal handler so that it writes the message // "Breaking out with signal %d\n" with the signal number that was // passed. Note that you cannot use printf() in a signal handler. // You must use write(). After writing the message, exit with return // code 37. // // HINT: If you fail integration tests and get a message that the // binary files are different, you may be writing an extra byte (the // null byte). You can make sure you avoid this by using strlen() // instead of trying to hard-code a length. char buf[128]; snprintf (buf, 128, "Breaking out with signal %d\n", signum); write (STDOUT_FILENO, buf, strlen (buf)); exit (37); } void catch_loop (int signum) { // sigaction(signum) // TODO: Override the signal handler for the signal number passed. // Then create a child that runs the following code: // prctl (PR_SET_PDEATHSIG, SIGKILL); // printf ("Child has started\n"); // fflush (stdout); // while (1) ; struct sigaction sa = { 0 }; sa.sa_handler = sig_handler; sigaction (signum, &sa, NULL); pid_t pid = fork (); if (pid == 0) { prctl (PR_SET_PDEATHSIG, SIGKILL); printf ("Child has started\n"); fflush (stdout); while (1) pause (); } // HINT: You will NOT call sig_handler() directly here. Instead, // you must use sigaction() to modify the signal's interrupt handler // so that sig_handler() will be called later when the signal occurs. // After starting the child, the parent will call sleep (1) to wait // for 1 second before sending the signal to the child. The parent // must wait for the child to run (and exit), then print // "Child was stopped with status %d\n" with the child process's exit // status code, retrieved with waitpid(). Note that you will need to // call WEXITSTATUS() on the retrieved status code. sleep (1); int status = 0; kill (pid, signum); waitpid (pid, &status, 0); printf ("Child was stopped with status %d\n", WEXITSTATUS (status)); }