Here's the latest win32 signals code, this time in the form of a patch
authorBruce Momjian
Tue, 27 Jan 2004 00:45:26 +0000 (00:45 +0000)
committerBruce Momjian
Tue, 27 Jan 2004 00:45:26 +0000 (00:45 +0000)
against the latest shapshot. It also includes the replacement of kill()
with pqkill() and sigsetmask() with pqsigsetmask().

Passes all tests fine on my linux machine once applied. Still doesn't
link completely on Win32 - there are a few things still required. But
much closer than before.

At Bruce's request, I'm goint to write up a README file about the method
of signals delivery chosen and why the others were rejected (basically a
summary of the mailinglist discussions). I'll finish that up once/if the
patch is accepted.

Magnus Hagander

src/backend/commands/async.c
src/backend/libpq/pqsignal.c
src/backend/main/main.c
src/backend/port/sysv_sema.c
src/backend/port/sysv_shmem.c
src/backend/postmaster/postmaster.c
src/backend/storage/ipc/pmsignal.c
src/backend/storage/lmgr/proc.c
src/backend/utils/init/miscinit.c
src/include/libpq/pqsignal.h

index bd90961315cb669a0fa9278ec6df95528ddccaa5..cbc7ee5146e7ea35f073eccf088f557020e32b6c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.107 2004/01/07 18:56:25 neilc Exp $
+ *   $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.108 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -83,6 +83,7 @@
 #include "commands/async.h"
 #include "libpq/libpq.h"
 #include "libpq/pqformat.h"
+#include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "storage/ipc.h"
 #include "tcop/tcopprot.h"
@@ -497,7 +498,7 @@ AtCommit_Notify(void)
             * for some reason.  It's OK to send the signal first, because
             * the other guy can't read pg_listener until we unlock it.
             */
-           if (kill(listenerPID, SIGUSR2) < 0)
+           if (pqkill(listenerPID, SIGUSR2) < 0)
            {
                /*
                 * Get rid of pg_listener entry if it refers to a PID that
index 497201e0a77a08edc817220ef7ca5b3049662c33..79d31b4ec73ae022fed2a14a788df88f27b704d2 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.28 2003/11/29 19:51:49 pgsql Exp $
+ *   $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.29 2004/01/27 00:45:26 momjian Exp $
  *
  * NOTES
  *     This shouldn't be in libpq, but the monitor and some other
  * is to do signal-handler reinstallation, which doesn't work well
  * at all.
  * ------------------------------------------------------------------------*/
+#ifdef WIN32
+#define WIN32_LEAN_AND_MEAN
+#define _WIN32_WINNT 0x0400
+#endif
+
 #include "postgres.h"
 
+#ifndef WIN32
 #include 
+#else
+#include 
+#endif
 
 #include "libpq/pqsignal.h"
 
@@ -127,6 +136,7 @@ pqinitmask(void)
 }
 
 
+#ifndef WIN32
 /*
  * Set up a signal handler
  */
@@ -149,3 +159,234 @@ pqsignal(int signo, pqsigfunc func)
    return oact.sa_handler;
 #endif   /* !HAVE_POSIX_SIGNALS */
 }
+
+
+#else
+
+
+/* Win32 specific signals code */
+
+/* pg_signal_crit_sec is used to protect only pg_signal_queue. That is the only
+ * variable that can be accessed from the signal sending threads! */
+static CRITICAL_SECTION pg_signal_crit_sec;
+static int pg_signal_queue;
+
+#define PG_SIGNAL_COUNT 32
+static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
+static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
+static int pg_signal_mask;
+
+HANDLE pgwin32_main_thread_handle;
+
+/* Signal handling thread function */
+static DWORD WINAPI pg_signal_thread(LPVOID param);
+
+/* Initialization */
+void pgwin32_signal_initialize(void) {
+  int i;
+  HANDLE signal_thread_handle;
+  InitializeCriticalSection(&pg_signal_crit_sec);
+  
+  for (i = 0; i < PG_SIGNAL_COUNT; i++) {
+    pg_signal_array[i] = SIG_DFL;
+    pg_signal_defaults[i] = SIG_IGN;
+  }
+  pg_signal_mask = 0;
+  pg_signal_queue = 0;
+  
+  /* Get handle to main thread so we can post calls to it later */
+  if (!DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),
+              GetCurrentProcess(),&pgwin32_main_thread_handle,
+              0,FALSE,DUPLICATE_SAME_ACCESS)) {
+    fprintf(stderr,gettext("Failed to get main thread handle!\n"));
+    exit(1);
+  }
+  
+  /* Create thread for handling signals */
+  signal_thread_handle = CreateThread(NULL,0,pg_signal_thread,NULL,0,NULL);
+  if (signal_thread_handle == NULL) {
+    fprintf(stderr,gettext("Failed to create signal handler thread!\n"));
+    exit(1);
+  }
+}
+
+
+/* Dispatch all signals currently queued and not blocked 
+ * Blocked signals are ignored, and will be fired at the time of
+ * the sigsetmask() call. */
+static void dispatch_queued_signals(void) {
+  int i;
+  
+  EnterCriticalSection(&pg_signal_crit_sec);
+  while (pg_signal_queue & ~pg_signal_mask) {
+    /* One or more unblocked signals queued for execution */
+    
+    int exec_mask = pg_signal_queue & ~pg_signal_mask;
+    
+    for (i = 0; i < PG_SIGNAL_COUNT; i++) {
+      if (exec_mask & sigmask(i)) {
+   /* Execute this signal */
+   pqsigfunc sig = pg_signal_array[i];
+   if (sig == SIG_DFL)
+     sig = pg_signal_defaults[i];
+   pg_signal_queue &= ~sigmask(i);
+   if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL) {
+     LeaveCriticalSection(&pg_signal_crit_sec);
+     sig(i);
+     EnterCriticalSection(&pg_signal_crit_sec);
+     break; /* Restart outer loop, in case signal mask or queue
+           has been modified inside signal handler */
+   }
+      }
+    }
+  }
+  LeaveCriticalSection(&pg_signal_crit_sec);
+}
+
+/* signal masking. Only called on main thread, no sync required */
+int pqsigsetmask(int mask) {
+  int prevmask;
+  prevmask = pg_signal_mask;
+  pg_signal_mask = mask;
+  
+  /* Dispatch any signals queued up right away, in case we have
+     unblocked one or more signals previously queued */
+  dispatch_queued_signals();
+  
+  return prevmask;
+}
+
+
+/* signal manipulation. Only called on main thread, no sync required */
+pqsigfunc pqsignal(int signum, pqsigfunc handler) {
+  pqsigfunc prevfunc;
+  if (signum >= PG_SIGNAL_COUNT || signum < 0)
+    return SIG_ERR;
+  prevfunc = pg_signal_array[signum];
+  pg_signal_array[signum] = handler;
+  return prevfunc;
+}
+
+/* signal sending */
+int pqkill(int pid, int sig) {
+  char pipename[128];
+  BYTE sigData = sig;
+  BYTE sigRet = 0;
+  DWORD bytes;
+  
+  if (sig >= PG_SIGNAL_COUNT || sig <= 0) {
+    errno = EINVAL;
+    return -1;
+  }
+  if (pid <= 0) {
+    /* No support for process groups */
+    errno = EINVAL;
+    return -1;
+  }
+  wsprintf(pipename,"\\\\.\\pipe\\pgsignal_%i",pid);
+  if (!CallNamedPipe(pipename,&sigData,1,&sigRet,1,&bytes,1000)) {
+    if (GetLastError() == ERROR_FILE_NOT_FOUND)
+      errno = ESRCH;
+    else if (GetLastError() == ERROR_ACCESS_DENIED)
+      errno = EPERM;
+    else
+      errno = EINVAL;
+    return -1;
+  }
+  if (bytes != 1 || sigRet != sig) {
+    errno = ESRCH;
+    return -1;
+  }
+  
+  return 0;
+}
+
+/* APC callback scheduled on main thread when signals are fired */
+static void CALLBACK pg_signal_apc(ULONG_PTR param) {
+  dispatch_queued_signals();
+}
+
+/*
+ * All functions below execute on the signal handler thread
+ * and must be synchronized as such!
+ * NOTE! The only global variable that can be used is
+ * pg_signal_queue!
+ */
+
+
+static void pg_queue_signal(int signum) {
+  if (signum >= PG_SIGNAL_COUNT || signum < 0)
+    return;
+  
+  EnterCriticalSection(&pg_signal_crit_sec);
+  pg_signal_queue |= sigmask(signum);
+  LeaveCriticalSection(&pg_signal_crit_sec);
+  
+  QueueUserAPC(pg_signal_apc,pgwin32_main_thread_handle,(ULONG_PTR)NULL);
+}
+
+/* Signal dispatching thread */
+static DWORD WINAPI pg_signal_dispatch_thread(LPVOID param) {
+  HANDLE pipe = (HANDLE)param;
+  BYTE sigNum;
+  DWORD bytes;
+  
+  if (!ReadFile(pipe,&sigNum,1,&bytes,NULL)) {
+    /* Client died before sending */
+    CloseHandle(pipe);
+    return 0;
+  }
+  if (bytes != 1) {
+    /* Received  bytes over signal pipe (should be 1) */
+    CloseHandle(pipe);
+    return 0;
+  }
+  WriteFile(pipe,&sigNum,1,&bytes,NULL); /* Don't care if it works or not.. */
+  FlushFileBuffers(pipe);
+  DisconnectNamedPipe(pipe);
+  CloseHandle(pipe);
+  
+  pg_queue_signal(sigNum);
+  return 0;
+}
+
+/* Signal handling thread */
+static DWORD WINAPI pg_signal_thread(LPVOID param) {
+  char pipename[128];
+  HANDLE pipe = INVALID_HANDLE_VALUE;
+  
+  wsprintf(pipename,"\\\\.\\pipe\\pgsignal_%i",GetCurrentProcessId());
+  
+  for (;;) {
+    BOOL fConnected;
+    HANDLE hThread;
+    
+    pipe = CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX,
+              PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
+              PIPE_UNLIMITED_INSTANCES,16,16,1000,NULL);
+    if (pipe == INVALID_HANDLE_VALUE) {
+      fprintf(stderr,gettext("Failed to create signal listener pipe: %i. Retrying.\n"),(int)GetLastError());
+      SleepEx(500,TRUE);
+      continue;
+    }
+    
+    fConnected = ConnectNamedPipe(pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
+    if (fConnected) {
+      hThread = CreateThread(NULL, 0, 
+                (LPTHREAD_START_ROUTINE)pg_signal_dispatch_thread,
+                (LPVOID)pipe,0,NULL);
+      if (hThread == INVALID_HANDLE_VALUE) {
+   fprintf(stderr,gettext("Failed to create signal dispatch thread: %i\n"),(int)GetLastError());
+      }
+      else 
+   CloseHandle(hThread);
+    }
+    else
+      /* Connection failed. Cleanup and try again */
+      CloseHandle(pipe);
+  }
+  return 0;
+}
+
+
+#endif
index fe8879940efb2e2e05993b856bdc5b019f4a15f5..90a1a35a3a5252414d6103533dfc8e3c9a92588c 100644 (file)
@@ -13,7 +13,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/main/main.c,v 1.71 2004/01/11 03:49:31 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/main/main.c,v 1.72 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -40,6 +40,9 @@
 #include "utils/help_config.h"
 #include "utils/ps_status.h"
 #include "pgstat.h"
+#ifdef WIN32
+#include "libpq/pqsignal.h"
+#endif
 
 
 
@@ -97,6 +100,8 @@ main(int argc, char *argv[])
                    argv[0], err);
            exit(1);
        }
+
+       pgwin32_signal_initialize();
    }
 #endif
 
index 20f0d6bc514dd7ccfac8118aef870029822e2b23..82d6ded95ba20a8221590fd55f4ca1900e3f009c 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/port/sysv_sema.c,v 1.12 2003/12/01 22:15:37 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/port/sysv_sema.c,v 1.13 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,6 +31,7 @@
 #include "miscadmin.h"
 #include "storage/ipc.h"
 #include "storage/pg_sema.h"
+#include "libpq/pqsignal.h"
 
 
 #ifndef HAVE_UNION_SEMUN
@@ -232,7 +233,7 @@ IpcSemaphoreCreate(int numSems)
            continue;           /* oops, GETPID failed */
        if (creatorPID != getpid())
        {
-           if (kill(creatorPID, 0) == 0 ||
+           if (pqkill(creatorPID, 0) == 0 ||
                errno != ESRCH)
                continue;       /* sema belongs to a live process */
        }
index 519714938a1a6093ace0dee78cfcac88418339f5..18b4a193f3f9ef2664b9918e4e3aa2052d5b48a6 100644 (file)
@@ -10,7 +10,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.28 2004/01/07 18:56:27 neilc Exp $
+ *   $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.29 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@
 #include "miscadmin.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
+#include "libpq/pqsignal.h"
 
 
 typedef key_t IpcMemoryKey;        /* shared memory key passed to shmget(2) */
@@ -284,7 +285,7 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
        hdr = (PGShmemHeader *) memAddress;
        if (hdr->creatorPID != getpid())
        {
-           if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
+           if (pqkill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
            {
                shmdt(memAddress);
                continue;       /* segment belongs to a live process */
index ccbffab56170e4f2cd47d263e41278d16c9f4564..ada86268e38dc3d85e493f32c28863cf2ae460f9 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.362 2004/01/26 22:59:53 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.363 2004/01/27 00:45:26 momjian Exp $
  *
  * NOTES
  *
@@ -1566,7 +1566,7 @@ processCancelRequest(Port *port, void *pkt)
                ereport(DEBUG2,
                        (errmsg_internal("processing cancel request: sending SIGINT to process %d",
                                         backendPID)));
-               kill(bp->pid, SIGINT);
+               pqkill(bp->pid, SIGINT);
            }
            else
                /* Right PID, wrong key: no way, Jose */
@@ -1738,7 +1738,7 @@ SIGHUP_handler(SIGNAL_ARGS)
         * will start a new one with a possibly changed config
         */
        if (BgWriterPID != 0)
-           kill(BgWriterPID, SIGTERM);
+           pqkill(BgWriterPID, SIGTERM);
    }
 
    PG_SETMASK(&UnBlockSig);
@@ -1772,7 +1772,7 @@ pmdie(SIGNAL_ARGS)
             * Wait for children to end their work and ShutdownDataBase.
             */
            if (BgWriterPID != 0)
-               kill(BgWriterPID, SIGTERM);
+               pqkill(BgWriterPID, SIGTERM);
            if (Shutdown >= SmartShutdown)
                break;
            Shutdown = SmartShutdown;
@@ -1806,7 +1806,7 @@ pmdie(SIGNAL_ARGS)
             * and exit) and ShutdownDataBase when they are gone.
             */
            if (BgWriterPID != 0)
-               kill(BgWriterPID, SIGTERM);
+               pqkill(BgWriterPID, SIGTERM);
            if (Shutdown >= FastShutdown)
                break;
            ereport(LOG,
@@ -1854,13 +1854,13 @@ pmdie(SIGNAL_ARGS)
             * properly shutdown data base system.
             */
            if (BgWriterPID != 0)
-               kill(BgWriterPID, SIGQUIT);
+               pqkill(BgWriterPID, SIGQUIT);
            ereport(LOG,
                    (errmsg("received immediate shutdown request")));
            if (ShutdownPID > 0)
-               kill(ShutdownPID, SIGQUIT);
+               pqkill(ShutdownPID, SIGQUIT);
            if (StartupPID > 0)
-               kill(StartupPID, SIGQUIT);
+               pqkill(StartupPID, SIGQUIT);
            if (DLGetHead(BackendList))
                SignalChildren(SIGQUIT);
            ExitPostmaster(0);
@@ -2130,7 +2130,7 @@ CleanupProc(int pid,
                        (errmsg_internal("sending %s to process %d",
                                         (SendStop ? "SIGSTOP" : "SIGQUIT"),
                                         (int) bp->pid)));
-               kill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT));
+               pqkill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT));
            }
        }
        else
@@ -2225,7 +2225,7 @@ SignalChildren(int signal)
                    (errmsg_internal("sending signal %d to process %d",
                                     signal,
                                     (int) bp->pid)));
-           kill(bp->pid, signal);
+           pqkill(bp->pid, signal);
        }
 
        curr = next;
index 2d6252b66caa12da3422dcb884286cd48adbba9c..58eb80fef081cb0bef067bea78742dbcb7decb6c 100644 (file)
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.11 2004/01/26 22:59:53 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.12 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "miscadmin.h"
 #include "storage/pmsignal.h"
 #include "storage/shmem.h"
+#include "libpq/pqsignal.h"
 
 
 /*
@@ -64,7 +65,7 @@ SendPostmasterSignal(PMSignalReason reason)
    /* Atomically set the proper flag */
    PMSignalFlags[reason] = true;
    /* Send signal to postmaster */
-   kill(PostmasterPid, SIGUSR1);
+   pqkill(PostmasterPid, SIGUSR1);
 }
 
 /*
index 682cc741f3562c6d213d073721cdc85845bfc83d..a3d4ad08874e70c3e4a993c69f102001b96aeb03 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.144 2004/01/07 18:56:27 neilc Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.145 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -51,6 +51,7 @@
 #include "storage/proc.h"
 #include "storage/sinval.h"
 #include "storage/spin.h"
+#include "libpq/pqsignal.h"
 
 /* GUC variables */
 int            DeadlockTimeout = 1000;
@@ -1130,7 +1131,7 @@ CheckStatementTimeout(void)
    {
        /* Time to die */
        statement_timeout_active = false;
-       kill(MyProcPid, SIGINT);
+       pqkill(MyProcPid, SIGINT);
    }
    else
    {
index 98de05c0b8f3929aa74e35eba249d0792851bc1b..2380cbb9dba848df22c9e1c7d5bf05dfe5295a6f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.120 2004/01/26 22:35:32 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.121 2004/01/27 00:45:26 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -32,6 +32,7 @@
 #include "catalog/catname.h"
 #include "catalog/pg_shadow.h"
 #include "libpq/libpq-be.h"
+#include "libpq/pqsignal.h"
 #include "miscadmin.h"
 #include "storage/ipc.h"
 #include "storage/pg_shmem.h"
@@ -531,7 +532,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
         */
        if (other_pid != my_pid)
        {
-           if (kill(other_pid, 0) == 0 ||
+           if (pqkill(other_pid, 0) == 0 ||
                (errno != ESRCH
 #ifdef __BEOS__
                 && errno != EINVAL
index 64ff18fedfda50a57d3245a9d7979e58ed6bf48b..c6c8a79b64cc8ea7ee6a9fc934b02407ce9d9ba9 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/libpq/pqsignal.h,v 1.23 2003/11/29 22:41:03 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/pqsignal.h,v 1.24 2004/01/27 00:45:26 momjian Exp $
  *
  * NOTES
  *   This shouldn't be in libpq, but the monitor and some other
 #ifndef PQSIGNAL_H
 #define PQSIGNAL_H
 
+#ifndef WIN32
 #include 
+#endif
+
+#ifndef WIN32
+#define pqkill(pid,sig) kill(pid,sig)
+#define pqsigsetmask(mask) sigsetmask(mask)
+#else
+int pqkill(int pid, int sig);
+int pqsigsetmask(int mask);
+#endif
+
 
 #ifdef HAVE_SIGPROCMASK
 extern sigset_t UnBlockSig,
@@ -31,7 +42,7 @@ extern int    UnBlockSig,
            BlockSig,
            AuthBlockSig;
 
-#define PG_SETMASK(mask)   sigsetmask(*((int*)(mask)))
+#define PG_SETMASK(mask)   pqsigsetmask(*((int*)(mask)))
 #endif
 
 typedef void (*pqsigfunc) (int);
@@ -40,4 +51,119 @@ extern void pqinitmask(void);
 
 extern pqsigfunc pqsignal(int signo, pqsigfunc func);
 
+#ifdef WIN32
+#define sigmask(sig) ( 1 << (sig-1) )
+
+void pgwin32_signal_initialize(void);
+extern HANDLE pgwin32_main_thread_handle;
+#define PG_POLL_SIGNALS() WaitForSingleObjectEx(pgwin32_main_thread_handle,0,TRUE);
+
+/* Define signal numbers. Override system values, since they are not
+   complete anyway */
+
+#undef SIGHUP
+#define    SIGHUP  1   /* hangup */
+
+#undef SIGINT  
+#define    SIGINT  2   /* interrupt */
+
+#undef SIGQUIT 
+#define    SIGQUIT 3   /* quit */
+
+#undef SIGILL  
+#define    SIGILL  4   /* illegal instruction (not reset when caught) */
+
+#undef SIGTRAP 
+#define    SIGTRAP 5   /* trace trap (not reset when caught) */
+
+#undef SIGABRT 
+#define    SIGABRT 6   /* abort(void) */
+
+#undef SIGIOT  
+#define    SIGIOT  SIGABRT /* compatibility */
+
+#undef SIGEMT  
+#define    SIGEMT  7   /* EMT instruction */
+
+#undef SIGFPE  
+#define    SIGFPE  8   /* floating point exception */
+
+#undef SIGKILL 
+#define    SIGKILL 9   /* kill (cannot be caught or ignored) */
+
+#undef SIGBUS  
+#define    SIGBUS  10  /* bus error */
+
+#undef SIGSEGV 
+#define    SIGSEGV 11  /* segmentation violation */
+
+#undef SIGSYS  
+#define    SIGSYS  12  /* non-existent system call invoked */
+
+#undef SIGSYS  
+#define    SIGPIPE 13  /* write on a pipe with no one to read it */
+
+#undef SIGALRM 
+#define    SIGALRM 14  /* alarm clock */
+
+#undef SIGTERM 
+#define    SIGTERM 15  /* software termination signal from kill */
+
+#undef SIGURG  
+#define    SIGURG  16  /* urgent condition on IO channel */
+
+#undef SIGSTOP 
+#define    SIGSTOP 17  /* sendable stop signal not from tty */
+
+#undef SIGTSTP 
+#define    SIGTSTP 18  /* stop signal from tty */
+
+#undef SIGCONT 
+#define    SIGCONT 19  /* continue a stopped process */
+
+#undef SIGCHLD 
+#define    SIGCHLD 20  /* to parent on child stop or exit */
+
+#undef SIGTTIN 
+#define    SIGTTIN 21  /* to readers pgrp upon background tty read */
+
+#undef SIGTTOU 
+#define    SIGTTOU 22  /* like TTIN for output if (tp->t_local<OSTOP) */
+
+#undef SIGIO   
+#define    SIGIO   23  /* input/output possible signal */
+
+#undef SIGXCPU 
+#define    SIGXCPU 24  /* exceeded CPU time limit */
+
+#undef SIGXFSZ 
+#define    SIGXFSZ 25  /* exceeded file size limit */
+
+#undef SIGVTALR
+#define    SIGVTALRM 26    /* virtual time alarm */
+
+#undef SIGPROF 
+#define    SIGPROF 27  /* profiling time alarm */
+
+#undef SIGWINCH 
+#define SIGWINCH 28    /* window size changes */
+
+#undef SIGINFO 
+#define SIGINFO    29  /* information request */
+
+#undef SIGUSR1 
+#define SIGUSR1 30 /* user defined signal 1 */
+
+#undef SIGUSR2 
+#define SIGUSR2 31 /* user defined signal 2 */
+
+#undef SIG_DFL
+#undef SIG_ERR
+#undef SIG_IGN
+#define SIG_DFL ((pqsigfunc)0)
+#define SIG_ERR ((pqsigfunc)-1)
+#define SIG_IGN ((pqsigfunc)1)
+
+#endif
+
 #endif   /* PQSIGNAL_H */