sighandlers.c 7.7 KB

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