blob: 5e4fe33c6a3126bcd79d3fa16693560cc2c43290 [file] [log] [blame]
Alexandre Julliard9037f4b2003-03-26 01:32:18 +00001/*
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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000019 */
20
21#include "config.h"
22
23#include <signal.h>
24#include <stdio.h>
Phil Krylov8e772c82006-03-24 03:49:50 +030025#include <sys/time.h>
Steven Edwards57279182005-03-04 12:38:36 +000026#ifdef HAVE_POLL_H
27#include <poll.h>
28#endif
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000029#ifdef HAVE_SYS_POLL_H
30#include <sys/poll.h>
31#endif
Mike McCormack0cd06262006-03-01 01:07:04 +090032#ifdef HAVE_SYS_RESOURCE_H
33#include <sys/resource.h>
34#endif
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000035#include <unistd.h>
36
37#include "file.h"
38#include "object.h"
39#include "process.h"
40#include "thread.h"
Alexandre Julliard3a4c04d2006-08-14 20:40:31 +020041#include "request.h"
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000042
Alexandre Julliardf9f37be2003-10-24 04:29:01 +000043#if defined(linux) && defined(__SIGRTMIN)
44/* the signal used by linuxthreads as exit signal for clone() threads */
45# define SIG_PTHREAD_CANCEL (__SIGRTMIN+1)
46#endif
47
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000048typedef void (*signal_callback)(void);
49
50struct handler
51{
52 struct object obj; /* object header */
53 struct fd *fd; /* file descriptor for the pipe side */
54 int pipe_write; /* unix fd for the pipe write side */
55 volatile int pending; /* is signal pending? */
56 signal_callback callback; /* callback function */
57};
58
59static void handler_dump( struct object *obj, int verbose );
60static void handler_destroy( struct object *obj );
61
62static const struct object_ops handler_ops =
63{
64 sizeof(struct handler), /* size */
65 handler_dump, /* dump */
Alexandre Julliard8382eb02007-12-05 18:16:42 +010066 no_get_type, /* get_type */
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000067 no_add_queue, /* add_queue */
68 NULL, /* remove_queue */
69 NULL, /* signaled */
70 NULL, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +000071 no_signal, /* signal */
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000072 no_get_fd, /* get_fd */
Alexandre Julliard28beba32005-12-12 14:57:40 +010073 no_map_access, /* map_access */
Rob Shearmanc1707d82007-10-03 13:10:37 +010074 default_get_sd, /* get_sd */
75 default_set_sd, /* set_sd */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +000076 no_lookup_name, /* lookup_name */
Alexandre Julliard7e71c1d2007-03-22 11:44:29 +010077 no_open_file, /* open_file */
Alexandre Julliardb9b1ea92005-06-09 15:39:52 +000078 no_close_handle, /* close_handle */
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000079 handler_destroy /* destroy */
80};
81
82static void handler_poll_event( struct fd *fd, int event );
83
84static const struct fd_ops handler_fd_ops =
85{
86 NULL, /* get_poll_events */
87 handler_poll_event, /* poll_event */
Alexandre Julliard3f057592007-04-12 20:21:53 +020088 NULL, /* flush */
89 NULL, /* get_fd_type */
Alexandre Julliard63571432007-04-16 14:45:03 +020090 NULL, /* ioctl */
Alexandre Julliard3f057592007-04-12 20:21:53 +020091 NULL, /* queue_async */
Alexandre Julliard72bff2e2007-04-10 17:07:27 +020092 NULL, /* reselect_async */
Alexandre Julliard3f057592007-04-12 20:21:53 +020093 NULL /* cancel_async */
Alexandre Julliard9037f4b2003-03-26 01:32:18 +000094};
95
96static struct handler *handler_sighup;
97static struct handler *handler_sigterm;
98static struct handler *handler_sigint;
99static struct handler *handler_sigchld;
100static struct handler *handler_sigio;
101
Alexandre Julliard9d99a042005-08-19 14:01:43 +0000102static int watchdog;
103
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000104/* create a signal handler */
105static struct handler *create_handler( signal_callback callback )
106{
107 struct handler *handler;
108 int fd[2];
109
110 if (pipe( fd ) == -1) return NULL;
111 if (!(handler = alloc_object( &handler_ops )))
112 {
113 close( fd[0] );
114 close( fd[1] );
115 return NULL;
116 }
117 handler->pipe_write = fd[1];
118 handler->pending = 0;
119 handler->callback = callback;
120
Alexandre Julliardf85437c2007-04-10 22:25:07 +0200121 if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj, 0 )))
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000122 {
123 release_object( handler );
124 return NULL;
125 }
126 set_fd_events( handler->fd, POLLIN );
Alexandre Julliardb00fb172006-03-22 20:32:04 +0100127 make_object_static( &handler->obj );
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000128 return handler;
129}
130
131/* handle a signal received for a given handler */
132static void do_signal( struct handler *handler )
133{
134 if (!handler->pending)
135 {
Alexandre Julliard17480ac2003-04-02 01:44:01 +0000136 char dummy = 0;
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000137 handler->pending = 1;
138 write( handler->pipe_write, &dummy, 1 );
139 }
140}
141
142static void handler_dump( struct object *obj, int verbose )
143{
144 struct handler *handler = (struct handler *)obj;
145 fprintf( stderr, "Signal handler fd=%p\n", handler->fd );
146}
147
148static void handler_destroy( struct object *obj )
149{
150 struct handler *handler = (struct handler *)obj;
151 if (handler->fd) release_object( handler->fd );
152 close( handler->pipe_write );
153}
154
155static void handler_poll_event( struct fd *fd, int event )
156{
157 struct handler *handler = get_fd_user( fd );
158
159 if (event & (POLLERR | POLLHUP))
160 {
161 /* this is not supposed to happen */
162 fprintf( stderr, "wineserver: Error on signal handler pipe\n" );
163 release_object( handler );
164 }
165 else if (event & POLLIN)
166 {
167 char dummy;
168
169 handler->pending = 0;
170 read( get_unix_fd( handler->fd ), &dummy, 1 );
171 handler->callback();
172 }
173}
174
175/* SIGHUP callback */
176static void sighup_callback(void)
177{
178#ifdef DEBUG_OBJECTS
179 dump_objects();
180#endif
181}
182
183/* SIGTERM callback */
184static void sigterm_callback(void)
185{
186 flush_registry();
187 exit(1);
188}
189
190/* SIGINT callback */
191static void sigint_callback(void)
192{
Alexandre Julliard3a4c04d2006-08-14 20:40:31 +0200193 shutdown_master_socket();
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000194}
195
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000196/* SIGHUP handler */
Robert Shearmanc5165712005-05-25 18:41:09 +0000197static void do_sighup( int signum )
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000198{
199 do_signal( handler_sighup );
200}
201
202/* SIGTERM handler */
Robert Shearmanc5165712005-05-25 18:41:09 +0000203static void do_sigterm( int signum )
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000204{
205 do_signal( handler_sigterm );
206}
207
208/* SIGINT handler */
Robert Shearmanc5165712005-05-25 18:41:09 +0000209static void do_sigint( int signum )
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000210{
211 do_signal( handler_sigint );
212}
213
Alexandre Julliard9d99a042005-08-19 14:01:43 +0000214/* SIGALRM handler */
215static void do_sigalrm( int signum )
216{
217 watchdog = 1;
218}
219
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000220/* SIGCHLD handler */
Robert Shearmanc5165712005-05-25 18:41:09 +0000221static void do_sigchld( int signum )
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000222{
223 do_signal( handler_sigchld );
224}
225
Mike McCormack0cd06262006-03-01 01:07:04 +0900226/* SIGSEGV handler */
227static void do_sigsegv( int signum )
228{
Alexandre Julliard6d1605a2007-06-25 14:13:21 +0200229 fprintf( stderr, "wineserver crashed, please enable coredumps (ulimit -c unlimited) and restart.\n");
Mike McCormack0cd06262006-03-01 01:07:04 +0900230 abort();
231}
232
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000233/* SIGIO handler */
Yorick Hardy3f11d482003-04-13 01:06:14 +0000234#ifdef HAVE_SIGINFO_T_SI_FD
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000235static void do_sigio( int signum, siginfo_t *si, void *x )
236{
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000237 do_signal( handler_sigio );
Alexandre Julliard3e588e32003-03-26 23:41:43 +0000238 do_change_notify( si->si_fd );
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000239}
Yorick Hardy3f11d482003-04-13 01:06:14 +0000240#endif
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000241
Alexandre Julliard9d99a042005-08-19 14:01:43 +0000242void start_watchdog(void)
243{
244 alarm( 3 );
245 watchdog = 0;
246}
247
248void stop_watchdog(void)
249{
250 alarm( 0 );
251 watchdog = 0;
252}
253
254int watchdog_triggered(void)
255{
256 return watchdog != 0;
257}
258
Mike McCormack0cd06262006-03-01 01:07:04 +0900259static int core_dump_disabled( void )
260{
261 int r = 0;
262#ifdef RLIMIT_CORE
263 struct rlimit lim;
264
265 r = !getrlimit(RLIMIT_CORE, &lim) && (lim.rlim_cur == 0);
266#endif
267 return r;
268}
269
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000270void init_signals(void)
271{
272 struct sigaction action;
Alexandre Julliardb00fb172006-03-22 20:32:04 +0100273 sigset_t blocked_sigset;
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000274
275 if (!(handler_sighup = create_handler( sighup_callback ))) goto error;
276 if (!(handler_sigterm = create_handler( sigterm_callback ))) goto error;
277 if (!(handler_sigint = create_handler( sigint_callback ))) goto error;
278 if (!(handler_sigchld = create_handler( sigchld_callback ))) goto error;
279 if (!(handler_sigio = create_handler( sigio_callback ))) goto error;
280
281 sigemptyset( &blocked_sigset );
282 sigaddset( &blocked_sigset, SIGCHLD );
283 sigaddset( &blocked_sigset, SIGHUP );
284 sigaddset( &blocked_sigset, SIGINT );
Alexandre Julliard9d99a042005-08-19 14:01:43 +0000285 sigaddset( &blocked_sigset, SIGALRM );
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000286 sigaddset( &blocked_sigset, SIGIO );
287 sigaddset( &blocked_sigset, SIGQUIT );
288 sigaddset( &blocked_sigset, SIGTERM );
Alexandre Julliardf9f37be2003-10-24 04:29:01 +0000289#ifdef SIG_PTHREAD_CANCEL
290 sigaddset( &blocked_sigset, SIG_PTHREAD_CANCEL );
291#endif
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000292
293 action.sa_mask = blocked_sigset;
294 action.sa_flags = 0;
295 action.sa_handler = do_sigchld;
296 sigaction( SIGCHLD, &action, NULL );
Alexandre Julliardf9f37be2003-10-24 04:29:01 +0000297#ifdef SIG_PTHREAD_CANCEL
298 sigaction( SIG_PTHREAD_CANCEL, &action, NULL );
299#endif
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000300 action.sa_handler = do_sighup;
301 sigaction( SIGHUP, &action, NULL );
302 action.sa_handler = do_sigint;
303 sigaction( SIGINT, &action, NULL );
Alexandre Julliard9d99a042005-08-19 14:01:43 +0000304 action.sa_handler = do_sigalrm;
305 sigaction( SIGALRM, &action, NULL );
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000306 action.sa_handler = do_sigterm;
307 sigaction( SIGQUIT, &action, NULL );
308 sigaction( SIGTERM, &action, NULL );
Mike McCormack0cd06262006-03-01 01:07:04 +0900309 if (core_dump_disabled())
310 {
311 action.sa_handler = do_sigsegv;
312 sigaction( SIGSEGV, &action, NULL );
313 }
Alexandre Julliard72f87b82004-05-01 02:50:06 +0000314 action.sa_handler = SIG_IGN;
315 sigaction( SIGXFSZ, &action, NULL );
Yorick Hardy3f11d482003-04-13 01:06:14 +0000316#ifdef HAVE_SIGINFO_T_SI_FD
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000317 action.sa_sigaction = do_sigio;
318 action.sa_flags = SA_SIGINFO;
319 sigaction( SIGIO, &action, NULL );
Yorick Hardy3f11d482003-04-13 01:06:14 +0000320#endif
Alexandre Julliard9037f4b2003-03-26 01:32:18 +0000321 return;
322
323error:
324 fprintf( stderr, "failed to initialize signal handlers\n" );
325 exit(1);
326}