Added generic signal handling mechanism based on pipes to synchronize
signals with the main poll loop.

diff --git a/server/signal.c b/server/signal.c
new file mode 100644
index 0000000..3388a66
--- /dev/null
+++ b/server/signal.c
@@ -0,0 +1,257 @@
+/*
+ * Server signal handling
+ *
+ * Copyright (C) 2003 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+
+#include <signal.h>
+#include <stdio.h>
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+#include <unistd.h>
+
+#include "file.h"
+#include "object.h"
+#include "process.h"
+#include "thread.h"
+
+typedef void (*signal_callback)(void);
+
+struct handler
+{
+    struct object    obj;         /* object header */
+    struct fd       *fd;          /* file descriptor for the pipe side */
+    int              pipe_write;  /* unix fd for the pipe write side */
+    volatile int     pending;     /* is signal pending? */
+    signal_callback  callback;    /* callback function */
+};
+
+static void handler_dump( struct object *obj, int verbose );
+static void handler_destroy( struct object *obj );
+
+static const struct object_ops handler_ops =
+{
+    sizeof(struct handler),   /* size */
+    handler_dump,             /* dump */
+    no_add_queue,             /* add_queue */
+    NULL,                     /* remove_queue */
+    NULL,                     /* signaled */
+    NULL,                     /* satisfied */
+    no_get_fd,                /* get_fd */
+    handler_destroy           /* destroy */
+};
+
+static void handler_poll_event( struct fd *fd, int event );
+
+static const struct fd_ops handler_fd_ops =
+{
+    NULL,                     /* get_poll_events */
+    handler_poll_event,       /* poll_event */
+    no_flush,                 /* flush */
+    no_get_file_info,         /* get_file_info */
+    no_queue_async            /* queue_async */
+};
+
+static struct handler *handler_sighup;
+static struct handler *handler_sigterm;
+static struct handler *handler_sigint;
+static struct handler *handler_sigchld;
+static struct handler *handler_sigio;
+
+static sigset_t blocked_sigset;
+
+/* create a signal handler */
+static struct handler *create_handler( signal_callback callback )
+{
+    struct handler *handler;
+    int fd[2];
+
+    if (pipe( fd ) == -1) return NULL;
+    if (!(handler = alloc_object( &handler_ops )))
+    {
+        close( fd[0] );
+        close( fd[1] );
+        return NULL;
+    }
+    handler->pipe_write = fd[1];
+    handler->pending    = 0;
+    handler->callback   = callback;
+
+    if (!(handler->fd = create_anonymous_fd( &handler_fd_ops, fd[0], &handler->obj )))
+    {
+        release_object( handler );
+        return NULL;
+    }
+    set_fd_events( handler->fd, POLLIN );
+    return handler;
+}
+
+/* handle a signal received for a given handler */
+static void do_signal( struct handler *handler )
+{
+    if (!handler->pending)
+    {
+        char dummy;
+        handler->pending = 1;
+        write( handler->pipe_write, &dummy, 1 );
+    }
+}
+
+static void handler_dump( struct object *obj, int verbose )
+{
+    struct handler *handler = (struct handler *)obj;
+    fprintf( stderr, "Signal handler fd=%p\n", handler->fd );
+}
+
+static void handler_destroy( struct object *obj )
+{
+    struct handler *handler = (struct handler *)obj;
+    if (handler->fd) release_object( handler->fd );
+    close( handler->pipe_write );
+}
+
+static void handler_poll_event( struct fd *fd, int event )
+{
+    struct handler *handler = get_fd_user( fd );
+
+    if (event & (POLLERR | POLLHUP))
+    {
+        /* this is not supposed to happen */
+        fprintf( stderr, "wineserver: Error on signal handler pipe\n" );
+        release_object( handler );
+    }
+    else if (event & POLLIN)
+    {
+        char dummy;
+
+        handler->pending = 0;
+        read( get_unix_fd( handler->fd ), &dummy, 1 );
+        handler->callback();
+    }
+}
+
+/* SIGHUP callback */
+static void sighup_callback(void)
+{
+#ifdef DEBUG_OBJECTS
+    dump_objects();
+#endif
+}
+
+/* SIGTERM callback */
+static void sigterm_callback(void)
+{
+    flush_registry();
+    exit(1);
+}
+
+/* SIGINT callback */
+static void sigint_callback(void)
+{
+    kill_all_processes( NULL, 1 );
+    flush_registry();
+    exit(1);
+}
+
+/* SIGIO callback */
+static void sigio_callback(void)
+{
+    /* nothing here yet */
+}
+
+/* SIGHUP handler */
+static void do_sighup()
+{
+    do_signal( handler_sighup );
+}
+
+/* SIGTERM handler */
+static void do_sigterm()
+{
+    do_signal( handler_sigterm );
+}
+
+/* SIGINT handler */
+static void do_sigint()
+{
+    do_signal( handler_sigint );
+}
+
+/* SIGCHLD handler */
+static void do_sigchld()
+{
+    do_signal( handler_sigchld );
+}
+
+/* SIGIO handler */
+static void do_sigio( int signum, siginfo_t *si, void *x )
+{
+    /* do_change_notify( si->si_fd ); */
+    do_signal( handler_sigio );
+}
+
+void init_signals(void)
+{
+    struct sigaction action;
+
+    if (!(handler_sighup  = create_handler( sighup_callback ))) goto error;
+    if (!(handler_sigterm = create_handler( sigterm_callback ))) goto error;
+    if (!(handler_sigint  = create_handler( sigint_callback ))) goto error;
+    if (!(handler_sigchld = create_handler( sigchld_callback ))) goto error;
+    if (!(handler_sigio   = create_handler( sigio_callback ))) goto error;
+
+    sigemptyset( &blocked_sigset );
+    sigaddset( &blocked_sigset, SIGCHLD );
+    sigaddset( &blocked_sigset, SIGHUP );
+    sigaddset( &blocked_sigset, SIGINT );
+    sigaddset( &blocked_sigset, SIGIO );
+    sigaddset( &blocked_sigset, SIGQUIT );
+    sigaddset( &blocked_sigset, SIGTERM );
+
+    action.sa_mask = blocked_sigset;
+    action.sa_flags = 0;
+    action.sa_handler = do_sigchld;
+    sigaction( SIGCHLD, &action, NULL );
+    action.sa_handler = do_sighup;
+    sigaction( SIGHUP, &action, NULL );
+    action.sa_handler = do_sigint;
+    sigaction( SIGINT, &action, NULL );
+    action.sa_handler = do_sigterm;
+    sigaction( SIGQUIT, &action, NULL );
+    sigaction( SIGTERM, &action, NULL );
+    action.sa_sigaction = do_sigio;
+    action.sa_flags = SA_SIGINFO;
+    sigaction( SIGIO, &action, NULL );
+    return;
+
+error:
+    fprintf( stderr, "failed to initialize signal handlers\n" );
+    exit(1);
+}
+
+void close_signals(void)
+{
+    sigprocmask( SIG_BLOCK, &blocked_sigset, NULL );
+    release_object( handler_sighup );
+    release_object( handler_sigterm );
+    release_object( handler_sigint );
+    release_object( handler_sigchld );
+    release_object( handler_sigio );
+}