1 /* 2 * Signal handlers 3 */ 4 5 #include "ctwm.h" 6 7 #include <signal.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <unistd.h> 11 #include <errno.h> 12 #include <sys/wait.h> 13 14 #include "ctwm_shutdown.h" 15 #include "signals.h" 16 17 18 /* Our backends */ 19 static void sh_restart(int signum); 20 static void sh_shutdown(int signum); 21 22 23 // Internal flags for which signals have called us 24 static bool sig_restart = false; 25 static bool sig_shutdown = false; 26 27 // External flag for whether some signal handler has set a flag that 28 // needs to trigger an action. 29 bool SignalFlag = false; 30 31 void ChildExit(int signum) 32 { 33 int Errno = errno; 34 /* reap dead children, ignore status */ 35 while (waitpid(-1, NULL, WNOHANG) > 0) 36 continue; 37 /* restore errno for interrupted sys calls */ 38 errno = Errno; 39 } 40 41 /** 42 * Setup signal handlers (run during startup) 43 */ 44 void 45 setup_signal_handlers(void) 46 { 47 // INT/QUIT/TERM: shutdown 48 // XXX Wildly unsafe handler; to be reworked 49 signal(SIGINT, sh_shutdown); 50 signal(SIGQUIT, sh_shutdown); 51 signal(SIGTERM, sh_shutdown); 52 53 // SIGHUP: restart 54 signal(SIGHUP, sh_restart); 55 56 // We don't use alarm(), but if we get the stray signal we shouldn't 57 // die... 58 signal(SIGALRM, SIG_IGN); 59 60 /* Setting SIGCHLD to SIG_IGN detaches children from the parent 61 * immediately, so it need not be waited for. 62 * In fact, you cannot wait for it, so a function like system() 63 * breaks. 64 */ 65 signal(SIGCHLD, ChildExit); 66 67 return; 68 } 69 70 71 /** 72 * Handle stuff set by a signal flag. Could be a Restart, could be a 73 * Shutdown... 74 */ 75 void 76 handle_signal_flag(Time t) 77 { 78 // Restarting? 79 if(sig_restart) { 80 // In case it fails, don't loop 81 sig_restart = false; 82 83 // Handle 84 DoRestart(t); 85 86 // Shouldn't return, but exec() might fail... 87 return; 88 } 89 90 // Shutting down? 91 if(sig_shutdown) { 92 // Doit 93 DoShutdown(); 94 95 // Can't return! 96 fprintf(stderr, "%s: DoShutdown() shouldn't return!\n", ProgramName); 97 exit(1); 98 } 99 100 // ??? 101 fprintf(stderr, "%s: Internal error: unexpected signal flag.\n", 102 ProgramName); 103 return; 104 } 105 106 107 108 /* 109 * Internal backend bits 110 */ 111 112 /** 113 * Set flag to restart. Backend for SIGHUP. 114 */ 115 static void 116 sh_restart(int signum) 117 { 118 // Signal handler; stdio isn't async-signal-safe, write(2) is 119 const char srf[] = ": signal received, setting restart flag\n"; 120 write(2, ProgramName, ProgramNameLen); 121 write(2, srf, sizeof(srf)); 122 123 SignalFlag = sig_restart = true; 124 } 125 126 /** 127 * Set flag to shutdown. Backend for SIGTERM etc. 128 */ 129 static void 130 sh_shutdown(int signum) 131 { 132 // Signal handler; stdio isn't async-signal-safe, write(2) is 133 const char srf[] = ": signal received, setting shutdown flag\n"; 134 write(2, ProgramName, ProgramNameLen); 135 write(2, srf, sizeof(srf)); 136 137 SignalFlag = sig_shutdown = true; 138 } 139 140