PageRenderTime 57ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/fpm/fpm_signals.c

http://github.com/dreamcat4/php-fpm
C | 252 lines | 214 code | 33 blank | 5 comment | 9 complexity | be1c3362d7cda87b590651ca05632cbf MD5 | raw file
  1. /* $Id: fpm_signals.c,v 1.24 2008/08/26 15:09:15 anight Exp $ */
  2. /* (c) 2007,2008 Andrei Nigmatulin */
  3. #include "fpm_config.h"
  4. #include <signal.h>
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include <errno.h>
  13. #include "fpm.h"
  14. #include "fpm_signals.h"
  15. #include "fpm_sockets.h"
  16. #include "fpm_php.h"
  17. #include "zlog.h"
  18. static int sp[2];
  19. const char *fpm_signal_names[NSIG + 1] = {
  20. #ifdef SIGHUP
  21. [SIGHUP] = "SIGHUP",
  22. #endif
  23. #ifdef SIGINT
  24. [SIGINT] = "SIGINT",
  25. #endif
  26. #ifdef SIGQUIT
  27. [SIGQUIT] = "SIGQUIT",
  28. #endif
  29. #ifdef SIGILL
  30. [SIGILL] = "SIGILL",
  31. #endif
  32. #ifdef SIGTRAP
  33. [SIGTRAP] = "SIGTRAP",
  34. #endif
  35. #ifdef SIGABRT
  36. [SIGABRT] = "SIGABRT",
  37. #endif
  38. #ifdef SIGEMT
  39. [SIGEMT] = "SIGEMT",
  40. #endif
  41. #ifdef SIGBUS
  42. [SIGBUS] = "SIGBUS",
  43. #endif
  44. #ifdef SIGFPE
  45. [SIGFPE] = "SIGFPE",
  46. #endif
  47. #ifdef SIGKILL
  48. [SIGKILL] = "SIGKILL",
  49. #endif
  50. #ifdef SIGUSR1
  51. [SIGUSR1] = "SIGUSR1",
  52. #endif
  53. #ifdef SIGSEGV
  54. [SIGSEGV] = "SIGSEGV",
  55. #endif
  56. #ifdef SIGUSR2
  57. [SIGUSR2] = "SIGUSR2",
  58. #endif
  59. #ifdef SIGPIPE
  60. [SIGPIPE] = "SIGPIPE",
  61. #endif
  62. #ifdef SIGALRM
  63. [SIGALRM] = "SIGALRM",
  64. #endif
  65. #ifdef SIGTERM
  66. [SIGTERM] = "SIGTERM",
  67. #endif
  68. #ifdef SIGCHLD
  69. [SIGCHLD] = "SIGCHLD",
  70. #endif
  71. #ifdef SIGCONT
  72. [SIGCONT] = "SIGCONT",
  73. #endif
  74. #ifdef SIGSTOP
  75. [SIGSTOP] = "SIGSTOP",
  76. #endif
  77. #ifdef SIGTSTP
  78. [SIGTSTP] = "SIGTSTP",
  79. #endif
  80. #ifdef SIGTTIN
  81. [SIGTTIN] = "SIGTTIN",
  82. #endif
  83. #ifdef SIGTTOU
  84. [SIGTTOU] = "SIGTTOU",
  85. #endif
  86. #ifdef SIGURG
  87. [SIGURG] = "SIGURG",
  88. #endif
  89. #ifdef SIGXCPU
  90. [SIGXCPU] = "SIGXCPU",
  91. #endif
  92. #ifdef SIGXFSZ
  93. [SIGXFSZ] = "SIGXFSZ",
  94. #endif
  95. #ifdef SIGVTALRM
  96. [SIGVTALRM] = "SIGVTALRM",
  97. #endif
  98. #ifdef SIGPROF
  99. [SIGPROF] = "SIGPROF",
  100. #endif
  101. #ifdef SIGWINCH
  102. [SIGWINCH] = "SIGWINCH",
  103. #endif
  104. #ifdef SIGINFO
  105. [SIGINFO] = "SIGINFO",
  106. #endif
  107. #ifdef SIGIO
  108. [SIGIO] = "SIGIO",
  109. #endif
  110. #ifdef SIGPWR
  111. [SIGPWR] = "SIGPWR",
  112. #endif
  113. #ifdef SIGSYS
  114. [SIGSYS] = "SIGSYS",
  115. #endif
  116. #ifdef SIGWAITING
  117. [SIGWAITING] = "SIGWAITING",
  118. #endif
  119. #ifdef SIGLWP
  120. [SIGLWP] = "SIGLWP",
  121. #endif
  122. #ifdef SIGFREEZE
  123. [SIGFREEZE] = "SIGFREEZE",
  124. #endif
  125. #ifdef SIGTHAW
  126. [SIGTHAW] = "SIGTHAW",
  127. #endif
  128. #ifdef SIGCANCEL
  129. [SIGCANCEL] = "SIGCANCEL",
  130. #endif
  131. #ifdef SIGLOST
  132. [SIGLOST] = "SIGLOST",
  133. #endif
  134. };
  135. static void sig_soft_quit(int signo)
  136. {
  137. int saved_errno = errno;
  138. /* closing fastcgi listening socket will force fcgi_accept() exit immediately */
  139. close(0);
  140. socket(AF_UNIX, SOCK_STREAM, 0);
  141. fpm_php_soft_quit();
  142. errno = saved_errno;
  143. }
  144. static void sig_handler(int signo)
  145. {
  146. static const char sig_chars[NSIG + 1] = {
  147. [SIGTERM] = 'T',
  148. [SIGINT] = 'I',
  149. [SIGUSR1] = '1',
  150. [SIGUSR2] = '2',
  151. [SIGQUIT] = 'Q',
  152. [SIGCHLD] = 'C'
  153. };
  154. char s;
  155. int saved_errno;
  156. if (fpm_globals.parent_pid != getpid()) {
  157. /* prevent a signal race condition when child process
  158. have not set up it's own signal handler yet */
  159. return;
  160. }
  161. saved_errno = errno;
  162. s = sig_chars[signo];
  163. write(sp[1], &s, sizeof(s));
  164. errno = saved_errno;
  165. }
  166. int fpm_signals_init_main()
  167. {
  168. struct sigaction act;
  169. if (0 > socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
  170. zlog(ZLOG_STUFF, ZLOG_SYSERROR, "socketpair() failed");
  171. return -1;
  172. }
  173. if (0 > fd_set_blocked(sp[0], 0) || 0 > fd_set_blocked(sp[1], 0)) {
  174. zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fd_set_blocked() failed");
  175. return -1;
  176. }
  177. if (0 > fcntl(sp[0], F_SETFD, FD_CLOEXEC) || 0 > fcntl(sp[1], F_SETFD, FD_CLOEXEC)) {
  178. zlog(ZLOG_STUFF, ZLOG_SYSERROR, "fcntl(F_SETFD, FD_CLOEXEC) failed");
  179. return -1;
  180. }
  181. memset(&act, 0, sizeof(act));
  182. act.sa_handler = sig_handler;
  183. sigfillset(&act.sa_mask);
  184. if (0 > sigaction(SIGTERM, &act, 0) ||
  185. 0 > sigaction(SIGINT, &act, 0) ||
  186. 0 > sigaction(SIGUSR1, &act, 0) ||
  187. 0 > sigaction(SIGUSR2, &act, 0) ||
  188. 0 > sigaction(SIGCHLD, &act, 0) ||
  189. 0 > sigaction(SIGQUIT, &act, 0)) {
  190. zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
  191. return -1;
  192. }
  193. return 0;
  194. }
  195. int fpm_signals_init_child()
  196. {
  197. struct sigaction act, act_dfl;
  198. memset(&act, 0, sizeof(act));
  199. memset(&act_dfl, 0, sizeof(act_dfl));
  200. act.sa_handler = &sig_soft_quit;
  201. act.sa_flags |= SA_RESTART;
  202. act_dfl.sa_handler = SIG_DFL;
  203. close(sp[0]);
  204. close(sp[1]);
  205. if (0 > sigaction(SIGTERM, &act_dfl, 0) ||
  206. 0 > sigaction(SIGINT, &act_dfl, 0) ||
  207. 0 > sigaction(SIGUSR1, &act_dfl, 0) ||
  208. 0 > sigaction(SIGUSR2, &act_dfl, 0) ||
  209. 0 > sigaction(SIGCHLD, &act_dfl, 0) ||
  210. 0 > sigaction(SIGQUIT, &act, 0)) {
  211. zlog(ZLOG_STUFF, ZLOG_SYSERROR, "sigaction() failed");
  212. return -1;
  213. }
  214. return 0;
  215. }
  216. int fpm_signals_get_fd()
  217. {
  218. return sp[0];
  219. }