signal.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Server signal handling
  3. *
  4. * Copyright (C) 2003 Alexandre Julliard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19. */
  20. #include "config.h"
  21. #include <signal.h>
  22. #include <stdio.h>
  23. #ifdef HAVE_SYS_POLL_H
  24. #include <sys/poll.h>
  25. #endif
  26. #include <unistd.h>
  27. #include "file.h"
  28. #include "object.h"
  29. #include "process.h"
  30. #include "thread.h"
  31. #if defined(linux) && defined(__SIGRTMIN)
  32. /* the signal used by linuxthreads as exit signal for clone() threads */
  33. # define SIG_PTHREAD_CANCEL (__SIGRTMIN+1)
  34. #endif
  35. typedef void (*signal_callback)(void);
  36. struct handler
  37. {
  38. struct object obj; /* object header */
  39. struct fd *fd; /* file descriptor for the pipe side */
  40. int pipe_write; /* unix fd for the pipe write side */
  41. volatile int pending; /* is signal pending? */
  42. signal_callback callback; /* callback function */
  43. };
  44. static void handler_dump( struct object *obj, int verbose );
  45. static void handler_destroy( struct object *obj );
  46. static const struct object_ops handler_ops =
  47. {
  48. sizeof(struct handler), /* size */
  49. handler_dump, /* dump */
  50. no_add_queue, /* add_queue */
  51. NULL, /* remove_queue */
  52. NULL, /* signaled */
  53. NULL, /* satisfied */
  54. no_get_fd, /* get_fd */
  55. handler_destroy /* destroy */
  56. };
  57. static void handler_poll_event( struct fd *fd, int event );
  58. static const struct fd_ops handler_fd_ops =
  59. {
  60. NULL, /* get_poll_events */
  61. handler_poll_event, /* poll_event */
  62. no_flush, /* flush */
  63. no_get_file_info, /* get_file_info */
  64. no_queue_async, /* queue_async */
  65. no_cancel_async /* cancel_async */
  66. };
  67. static struct handler *handler_sighup;
  68. static struct handler *handler_sigterm;
  69. static struct handler *handler_sigint;
  70. static struct handler *handler_sigchld;
  71. static struct handler *handler_sigio;
  72. static sigset_t blocked_sigset;
  73. /* create a signal handler */
  74. static struct handler *create_handler( signal_callback callback )
  75. {
  76. struct handler *handler;
  77. int fd[2];
  78. if (pipe( fd ) == -1) return NULL;
  79. if (!(handler = alloc_object( &handler_ops )))
  80. {
  81. close( fd[0] );
  82. close( fd[1] );
  83. return NULL;
  84. }
  85. handler->pipe_write = fd[1];
  86. handler->pending = 0;
  87. handler->callback = callback;
  88. if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj )))
  89. {
  90. release_object( handler );
  91. return NULL;
  92. }
  93. set_fd_events( handler->fd, POLLIN );
  94. return handler;
  95. }
  96. /* handle a signal received for a given handler */
  97. static void do_signal( struct handler *handler )
  98. {
  99. if (!handler->pending)
  100. {
  101. char dummy = 0;
  102. handler->pending = 1;
  103. write( handler->pipe_write, &dummy, 1 );
  104. }
  105. }
  106. static void handler_dump( struct object *obj, int verbose )
  107. {
  108. struct handler *handler = (struct handler *)obj;
  109. fprintf( stderr, "Signal handler fd=%p\n", handler->fd );
  110. }
  111. static void handler_destroy( struct object *obj )
  112. {
  113. struct handler *handler = (struct handler *)obj;
  114. if (handler->fd) release_object( handler->fd );
  115. close( handler->pipe_write );
  116. }
  117. static void handler_poll_event( struct fd *fd, int event )
  118. {
  119. struct handler *handler = get_fd_user( fd );
  120. if (event & (POLLERR | POLLHUP))
  121. {
  122. /* this is not supposed to happen */
  123. fprintf( stderr, "wineserver: Error on signal handler pipe\n" );
  124. release_object( handler );
  125. }
  126. else if (event & POLLIN)
  127. {
  128. char dummy;
  129. handler->pending = 0;
  130. read( get_unix_fd( handler->fd ), &dummy, 1 );
  131. handler->callback();
  132. }
  133. }
  134. /* SIGHUP callback */
  135. static void sighup_callback(void)
  136. {
  137. #ifdef DEBUG_OBJECTS
  138. dump_objects();
  139. #endif
  140. }
  141. /* SIGTERM callback */
  142. static void sigterm_callback(void)
  143. {
  144. flush_registry();
  145. exit(1);
  146. }
  147. /* SIGINT callback */
  148. static void sigint_callback(void)
  149. {
  150. kill_all_processes( NULL, 1 );
  151. flush_registry();
  152. exit(1);
  153. }
  154. /* SIGHUP handler */
  155. static void do_sighup()
  156. {
  157. do_signal( handler_sighup );
  158. }
  159. /* SIGTERM handler */
  160. static void do_sigterm()
  161. {
  162. do_signal( handler_sigterm );
  163. }
  164. /* SIGINT handler */
  165. static void do_sigint()
  166. {
  167. do_signal( handler_sigint );
  168. }
  169. /* SIGCHLD handler */
  170. static void do_sigchld()
  171. {
  172. do_signal( handler_sigchld );
  173. }
  174. /* SIGIO handler */
  175. #ifdef HAVE_SIGINFO_T_SI_FD
  176. static void do_sigio( int signum, siginfo_t *si, void *x )
  177. {
  178. do_signal( handler_sigio );
  179. do_change_notify( si->si_fd );
  180. }
  181. #endif
  182. void init_signals(void)
  183. {
  184. struct sigaction action;
  185. if (!(handler_sighup = create_handler( sighup_callback ))) goto error;
  186. if (!(handler_sigterm = create_handler( sigterm_callback ))) goto error;
  187. if (!(handler_sigint = create_handler( sigint_callback ))) goto error;
  188. if (!(handler_sigchld = create_handler( sigchld_callback ))) goto error;
  189. if (!(handler_sigio = create_handler( sigio_callback ))) goto error;
  190. sigemptyset( &blocked_sigset );
  191. sigaddset( &blocked_sigset, SIGCHLD );
  192. sigaddset( &blocked_sigset, SIGHUP );
  193. sigaddset( &blocked_sigset, SIGINT );
  194. sigaddset( &blocked_sigset, SIGIO );
  195. sigaddset( &blocked_sigset, SIGQUIT );
  196. sigaddset( &blocked_sigset, SIGTERM );
  197. #ifdef SIG_PTHREAD_CANCEL
  198. sigaddset( &blocked_sigset, SIG_PTHREAD_CANCEL );
  199. #endif
  200. action.sa_mask = blocked_sigset;
  201. action.sa_flags = 0;
  202. action.sa_handler = do_sigchld;
  203. sigaction( SIGCHLD, &action, NULL );
  204. #ifdef SIG_PTHREAD_CANCEL
  205. sigaction( SIG_PTHREAD_CANCEL, &action, NULL );
  206. #endif
  207. action.sa_handler = do_sighup;
  208. sigaction( SIGHUP, &action, NULL );
  209. action.sa_handler = do_sigint;
  210. sigaction( SIGINT, &action, NULL );
  211. action.sa_handler = do_sigterm;
  212. sigaction( SIGQUIT, &action, NULL );
  213. sigaction( SIGTERM, &action, NULL );
  214. action.sa_handler = SIG_IGN;
  215. sigaction( SIGXFSZ, &action, NULL );
  216. #ifdef HAVE_SIGINFO_T_SI_FD
  217. action.sa_sigaction = do_sigio;
  218. action.sa_flags = SA_SIGINFO;
  219. sigaction( SIGIO, &action, NULL );
  220. #endif
  221. return;
  222. error:
  223. fprintf( stderr, "failed to initialize signal handlers\n" );
  224. exit(1);
  225. }
  226. void close_signals(void)
  227. {
  228. sigprocmask( SIG_BLOCK, &blocked_sigset, NULL );
  229. release_object( handler_sighup );
  230. release_object( handler_sigterm );
  231. release_object( handler_sigint );
  232. release_object( handler_sigchld );
  233. release_object( handler_sigio );
  234. }