From 50491963cb6e439f09e4ade608c0c177ed6e6527 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Tue, 27 Jan 2004 00:45:26 +0000
Subject: [PATCH] Here's the latest win32 signals code, this time in the form
 of a patch 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        |   5 +-
 src/backend/libpq/pqsignal.c        | 243 +++++++++++++++++++++++++++-
 src/backend/main/main.c             |   7 +-
 src/backend/port/sysv_sema.c        |   5 +-
 src/backend/port/sysv_shmem.c       |   5 +-
 src/backend/postmaster/postmaster.c |  20 +--
 src/backend/storage/ipc/pmsignal.c  |   5 +-
 src/backend/storage/lmgr/proc.c     |   5 +-
 src/backend/utils/init/miscinit.c   |   5 +-
 src/include/libpq/pqsignal.h        | 130 ++++++++++++++-
 10 files changed, 404 insertions(+), 26 deletions(-)

diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index bd90961315c..cbc7ee5146e 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -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
diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c
index 497201e0a77..79d31b4ec73 100644
--- a/src/backend/libpq/pqsignal.c
+++ b/src/backend/libpq/pqsignal.c
@@ -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
@@ -38,9 +38,18 @@
  *	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 <signal.h>
+#else
+#include <windows.h>
+#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> 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
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index fe8879940ef..90a1a35a3a5 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -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
 
diff --git a/src/backend/port/sysv_sema.c b/src/backend/port/sysv_sema.c
index 20f0d6bc514..82d6ded95ba 100644
--- a/src/backend/port/sysv_sema.c
+++ b/src/backend/port/sysv_sema.c
@@ -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 */
 		}
diff --git a/src/backend/port/sysv_shmem.c b/src/backend/port/sysv_shmem.c
index 519714938a1..18b4a193f3f 100644
--- a/src/backend/port/sysv_shmem.c
+++ b/src/backend/port/sysv_shmem.c
@@ -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 */
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index ccbffab5617..ada86268e38 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -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;
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
index 2d6252b66ca..58eb80fef08 100644
--- a/src/backend/storage/ipc/pmsignal.c
+++ b/src/backend/storage/ipc/pmsignal.c
@@ -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);
 }
 
 /*
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 682cc741f35..a3d4ad08874 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -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
 	{
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index 98de05c0b8f..2380cbb9dba 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -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
diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h
index 64ff18fedfd..c6c8a79b64c 100644
--- a/src/include/libpq/pqsignal.h
+++ b/src/include/libpq/pqsignal.h
@@ -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
@@ -18,7 +18,18 @@
 #ifndef PQSIGNAL_H
 #define PQSIGNAL_H
 
+#ifndef WIN32
 #include <signal.h>
+#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&LTOSTOP) */
+
+#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 */
-- 
GitLab