sighandlers.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. * Please read the file COPYING, README and AUTHORS for more information.
  10. */
  11. #include "portab.h"
  12. /**
  13. * @file
  14. * Signal Handlers: Actions to be performed when the program
  15. * receives a signal.
  16. */
  17. #include <errno.h>
  18. #include <unistd.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <signal.h>
  22. #include <sys/types.h>
  23. #include <sys/wait.h>
  24. #include "imp.h"
  25. #include "conn.h"
  26. #include "conf-ssl.h"
  27. #include "channel.h"
  28. #include "conf.h"
  29. #include "io.h"
  30. #include "log.h"
  31. #include "ngircd.h"
  32. #include "sighandlers.h"
  33. static int signalpipe[2];
  34. static const int signals_catch[] = {
  35. SIGINT, SIGQUIT, SIGTERM, SIGHUP, SIGCHLD, SIGUSR1, SIGUSR2
  36. };
  37. #ifdef DEBUG
  38. static void
  39. Dump_State(void)
  40. {
  41. Log(LOG_DEBUG, "--- Internal server state: %s ---",
  42. Client_ID(Client_ThisServer()));
  43. Log(LOG_DEBUG, "time()=%ld", time(NULL));
  44. Conf_DebugDump();
  45. Conn_DebugDump();
  46. Client_DebugDump();
  47. Log(LOG_DEBUG, "--- End of state dump ---");
  48. } /* Dump_State */
  49. #endif
  50. static void
  51. Signal_Block(int sig)
  52. {
  53. #ifdef HAVE_SIGPROCMASK
  54. sigset_t set;
  55. sigemptyset(&set);
  56. sigaddset(&set, sig);
  57. sigprocmask(SIG_BLOCK, &set, NULL);
  58. #else
  59. sigblock(sig);
  60. #endif
  61. }
  62. static void
  63. Signal_Unblock(int sig)
  64. {
  65. #ifdef HAVE_SIGPROCMASK
  66. sigset_t set;
  67. sigemptyset(&set);
  68. sigaddset(&set, sig);
  69. sigprocmask(SIG_UNBLOCK, &set, NULL);
  70. #else
  71. int old = sigblock(0) & ~sig;
  72. sigsetmask(old);
  73. #endif
  74. }
  75. /**
  76. * Reload the server configuration file.
  77. */
  78. static void
  79. Rehash(void)
  80. {
  81. char old_name[CLIENT_ID_LEN];
  82. unsigned old_nicklen;
  83. Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
  84. /* Remember old server name and nickname length */
  85. strlcpy( old_name, Conf_ServerName, sizeof old_name );
  86. old_nicklen = Conf_MaxNickLength;
  87. /* Re-read configuration ... */
  88. if (!Conf_Rehash( ))
  89. return;
  90. /* Close down all listening sockets */
  91. Conn_ExitListeners( );
  92. /* Recover old server name and nickname length: these values can't
  93. * be changed during run-time */
  94. if (strcmp(old_name, Conf_ServerName) != 0 ) {
  95. strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
  96. Log(LOG_ERR,
  97. "Can't change \"ServerName\" on runtime! Ignored new name.");
  98. }
  99. if (old_nicklen != Conf_MaxNickLength) {
  100. Conf_MaxNickLength = old_nicklen;
  101. Log(LOG_ERR,
  102. "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
  103. }
  104. /* Create new pre-defined channels */
  105. Channel_InitPredefined( );
  106. if (!ConnSSL_InitLibrary())
  107. Log(LOG_WARNING,
  108. "Re-Initializing of SSL failed, using old keys!");
  109. /* Start listening on sockets */
  110. Conn_InitListeners( );
  111. /* Sync configuration with established connections */
  112. Conn_SyncServerStruct( );
  113. Log( LOG_NOTICE|LOG_snotice, "Re-reading of configuration done." );
  114. } /* Rehash */
  115. /**
  116. * Signal handler of ngIRCd.
  117. * This function is called whenever ngIRCd catches a signal sent by the
  118. * user and/or the system to it. For example SIGTERM and SIGHUP.
  119. *
  120. * It blocks the signal and queues it for later execution by Signal_Handler_BH.
  121. * @param Signal Number of the signal to handle.
  122. */
  123. static void
  124. Signal_Handler(int Signal)
  125. {
  126. switch (Signal) {
  127. case SIGTERM:
  128. case SIGINT:
  129. case SIGQUIT:
  130. /* shut down sever */
  131. NGIRCd_SignalQuit = true;
  132. return;
  133. case SIGCHLD:
  134. /* child-process exited, avoid zombies */
  135. while (waitpid( -1, NULL, WNOHANG) > 0)
  136. ;
  137. return;
  138. #ifdef DEBUG
  139. case SIGUSR1:
  140. if (! NGIRCd_Debug) {
  141. Log(LOG_INFO|LOG_snotice,
  142. "Got SIGUSR1, debug mode activated.");
  143. #ifdef SNIFFER
  144. strcpy(NGIRCd_DebugLevel, "2");
  145. NGIRCd_Debug = true;
  146. NGIRCd_Sniffer = true;
  147. #else
  148. strcpy(NGIRCd_DebugLevel, "1");
  149. NGIRCd_Debug = true;
  150. #endif /* SNIFFER */
  151. } else {
  152. Log(LOG_INFO|LOG_snotice,
  153. "Got SIGUSR1, debug mode deactivated.");
  154. strcpy(NGIRCd_DebugLevel, "");
  155. NGIRCd_Debug = false;
  156. #ifdef SNIFFER
  157. NGIRCd_Sniffer = false;
  158. #endif /* SNIFFER */
  159. }
  160. return;
  161. #endif
  162. }
  163. /*
  164. * other signal: queue for later execution.
  165. * This has the advantage that we are not restricted
  166. * to functions that can be called safely from signal handlers.
  167. */
  168. if (write(signalpipe[1], &Signal, sizeof(Signal)) != -1)
  169. Signal_Block(Signal);
  170. } /* Signal_Handler */
  171. /**
  172. * Signal processing handler of ngIRCd.
  173. * This function is called from the main conn event loop in (io_dispatch)
  174. * whenever ngIRCd has queued a signal.
  175. *
  176. * This function runs in normal context, not from the real signal handler,
  177. * thus its not necessary to only use functions that are signal safe.
  178. * @param Signal Number of the signal that was queued.
  179. */
  180. static void
  181. Signal_Handler_BH(int Signal)
  182. {
  183. switch (Signal) {
  184. case SIGHUP:
  185. /* re-read configuration */
  186. Rehash();
  187. break;
  188. #ifdef DEBUG
  189. case SIGUSR2:
  190. if (NGIRCd_Debug) {
  191. Log(LOG_INFO|LOG_snotice,
  192. "Got SIGUSR2, dumping internal state ...");
  193. Dump_State();
  194. }
  195. break;
  196. default:
  197. Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);
  198. #endif
  199. }
  200. Signal_Unblock(Signal);
  201. }
  202. static void
  203. Signal_Callback(int fd, short UNUSED what)
  204. {
  205. int sig, ret;
  206. (void) what;
  207. do {
  208. ret = (int)read(fd, &sig, sizeof(sig));
  209. if (ret == sizeof(int))
  210. Signal_Handler_BH(sig);
  211. } while (ret == sizeof(int));
  212. if (ret == -1) {
  213. if (errno == EAGAIN || errno == EINTR)
  214. return;
  215. Log(LOG_EMERG, "Read from signal pipe: %s - Exiting!",
  216. strerror(errno));
  217. exit(1);
  218. }
  219. Log(LOG_EMERG, "EOF on signal pipe!? - Exiting!");
  220. exit(1);
  221. }
  222. /**
  223. * Initialize the signal handlers, catch
  224. * those signals we are interested in and sets SIGPIPE to be ignored.
  225. * @return true if initialization was successful.
  226. */
  227. bool
  228. Signals_Init(void)
  229. {
  230. size_t i;
  231. #ifdef HAVE_SIGACTION
  232. struct sigaction saction;
  233. #endif
  234. if (signalpipe[0] > 0 || signalpipe[1] > 0)
  235. return true;
  236. if (pipe(signalpipe))
  237. return false;
  238. if (!io_setnonblock(signalpipe[0]) ||
  239. !io_setnonblock(signalpipe[1]))
  240. return false;
  241. if (!io_setcloexec(signalpipe[0]) ||
  242. !io_setcloexec(signalpipe[1]))
  243. return false;
  244. #ifdef HAVE_SIGACTION
  245. memset( &saction, 0, sizeof( saction ));
  246. saction.sa_handler = Signal_Handler;
  247. #ifdef SA_RESTART
  248. saction.sa_flags |= SA_RESTART;
  249. #endif
  250. #ifdef SA_NOCLDWAIT
  251. saction.sa_flags |= SA_NOCLDWAIT;
  252. #endif
  253. for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
  254. sigaction(signals_catch[i], &saction, NULL);
  255. /* we handle write errors properly; ignore SIGPIPE */
  256. saction.sa_handler = SIG_IGN;
  257. sigaction(SIGPIPE, &saction, NULL);
  258. #else
  259. for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
  260. signal(signals_catch[i], Signal_Handler);
  261. signal(SIGPIPE, SIG_IGN);
  262. #endif
  263. return io_event_create(signalpipe[0], IO_WANTREAD, Signal_Callback);
  264. } /* Signals_Init */
  265. /**
  266. * Restores signals to their default behavior.
  267. *
  268. * This should be called after a fork() in the new
  269. * child prodcess, especially when we are about to call
  270. * 3rd party code (e.g. PAM).
  271. */
  272. void
  273. Signals_Exit(void)
  274. {
  275. size_t i;
  276. #ifdef HAVE_SIGACTION
  277. struct sigaction saction;
  278. memset(&saction, 0, sizeof(saction));
  279. saction.sa_handler = SIG_DFL;
  280. for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
  281. sigaction(signals_catch[i], &saction, NULL);
  282. sigaction(SIGPIPE, &saction, NULL);
  283. #else
  284. for (i=0; i < C_ARRAY_SIZE(signals_catch) ; i++)
  285. signal(signals_catch[i], SIG_DFL);
  286. signal(SIGPIPE, SIG_DFL);
  287. #endif
  288. close(signalpipe[1]);
  289. close(signalpipe[0]);
  290. signalpipe[0] = signalpipe[1] = 0;
  291. }
  292. /* -eof- */