Revised patch to avoid "lost signals before signaling mechanism is set up
in Win32". This was tested by plus a line:

        Sleep(10*1000);

in the front of pgwin32_signal_initialize().


Regards,
Qingqing
Index: src/port/kill.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/port/kill.c,v
retrieving revision 1.6
diff -c -r1.6 kill.c
*** src/port/kill.c     31 Dec 2004 22:03:53 -0000      1.6
--- src/port/kill.c     4 Jun 2005 12:16:07 -0000
***************
*** 17,61 ****
  #include "c.h"
  
  #ifdef WIN32
! /* signal sending */
  int
  pgkill(int pid, int sig)
  {
!       char            pipename[128];
!       BYTE            sigData = sig;
!       BYTE            sigRet = 0;
!       DWORD           bytes;
  
!       /* we allow signal 0 here, but it will be ignored in pg_queue_signal */
        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;
  }
  
  #endif
--- 17,120 ----
  #include "c.h"
  
  #ifdef WIN32
! 
! /* Convenience macro to set errno and return */
! #define set_error_and_return(e)       \
! do{   \
!       if (shmem)      UnmapViewOfFile(shmem); \
!       if (hShmem)     CloseHandle(hShmem);    \
!       if (hEvent)     CloseHandle(hEvent);    \
!       if (hMutex)     CloseHandle(hMutex);    \
!       \
!       errno = (e); \
!       return ((e) == 0)? 0 : -1;      \
! } while (0)
! 
! /* 
!  * pgkill
!  *            kill() win32 emulation. 
!  *
!  *            pgkill() will fail if: 
!  *            [EINVAL] The value of the sig argument is an invalid 
!  *                             or target process id <= 0.
!  *            [ESRCH]  No process can be found corresponding to that 
!  *                             specified by pid.  
!  *            [EPERM]  Any other win32 system call fails.
!  */
  int
  pgkill(int pid, int sig)
  {
!       char    name[64];
!       HANDLE  hShmem, hMutex, hEvent;
!       Win32SignalShmemStruct *shmem;
! 
!       shmem  = NULL;
!       hShmem = NULL;
!       hMutex = NULL;
!       hEvent = NULL;
  
!       /* we allow signal 0 here, and handle later */
        if (sig >= PG_SIGNAL_COUNT || sig < 0)
!               set_error_and_return(EINVAL);
!       
!       /* No support for process groups */
        if (pid <= 0)
!               set_error_and_return(EINVAL);
!       
!       /* 
!        * Attach to the signaling shared memory. If it is attachable,
!        * we decide that the process is alive. 
!        */
!       wsprintf(name, "%s.%d", SIGNAL_SHMEM_PREFIX, pid);
!       if (NULL == (hShmem = OpenFileMapping(FILE_MAP_ALL_ACCESS, 
!                                                               FALSE, 
!                                                               name)))
!               set_error_and_return(ESRCH);
!       
!       if (sig == 0)
!               set_error_and_return(0);
! 
!       if (NULL == (shmem = MapViewOfFile(hShmem,         
!                                                       FILE_MAP_ALL_ACCESS,   
!                                                       0, 0, 0)))        
!               set_error_and_return(EPERM);
! 
!       /* Grab the mutex */
!       wsprintf(name, "%s.%d", SIGNAL_MUTEX_PREFIX, pid);
!       if (NULL == (hMutex = OpenMutex(MUTEX_ALL_ACCESS, 
!                                                               FALSE, name)))
!               set_error_and_return(EPERM);
! 
!       if (WaitForSingleObject(hMutex, INFINITE) != WAIT_OBJECT_0)     
!               set_error_and_return(EPERM);
! 
!       /* Write down the signal number */
!       shmem->queue |= sigmask(sig);
!       
!       /* 
!        * If we can't release the mutex, we have to exit the
!        * process to make mutex released by the system. If we 
!        * can't set the event, that's really awkward, but the 
!        * target process would find out the signal when next
!        * set event is successfully done. 
!        */
!       if (!ReleaseMutex(hMutex))
!               set_error_and_return(EPERM);
! 
!       if (!UnmapViewOfFile(shmem))
!               set_error_and_return(EPERM);
! 
!       /* Set event */
!       wsprintf(name, "%s.%d", SIGNAL_EVENT_PREFIX, pid);
!       if (NULL == (hEvent = OpenEvent(EVENT_ALL_ACCESS, 
!                                                               FALSE, name)))
!               set_error_and_return(EPERM);
! 
!       if (!SetEvent(hEvent))
!               set_error_and_return(EPERM);
  
!       /* Successfully done */
!       set_error_and_return(0);
  }
  
  #endif
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/postmaster.c,v
retrieving revision 1.451
diff -c -r1.451 postmaster.c
*** src/backend/postmaster/postmaster.c 15 May 2005 00:26:18 -0000      1.451
--- src/backend/postmaster/postmaster.c 4 Jun 2005 12:29:17 -0000
***************
*** 332,338 ****
        pid_t PostmasterPid;
  #ifdef WIN32
        HANDLE PostmasterHandle;
!       HANDLE initial_signal_pipe;
        HANDLE syslogPipe[2];
  #else
        int syslogPipe[2];
--- 332,338 ----
        pid_t PostmasterPid;
  #ifdef WIN32
        HANDLE PostmasterHandle;
!       HANDLE initial_signal_handles[N_SIGNALING_HANDLES];
        HANDLE syslogPipe[2];
  #else
        int syslogPipe[2];
***************
*** 3561,3567 ****
  #define write_inheritable_socket(dest, src, childpid) (*(dest) = (src))
  #define read_inheritable_socket(dest, src) (*(dest) = *(src))
  #else
! static void write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE child);
  static void write_inheritable_socket(InheritableSocket *dest, SOCKET src,
                                                                         pid_t 
childPid);
  static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
--- 3561,3567 ----
  #define write_inheritable_socket(dest, src, childpid) (*(dest) = (src))
  #define read_inheritable_socket(dest, src) (*(dest) = *(src))
  #else
! static void write_duplicated_handles(int num, HANDLE *dest, HANDLE *src, 
HANDLE child);
  static void write_inheritable_socket(InheritableSocket *dest, SOCKET src,
                                                                         pid_t 
childPid);
  static void read_inheritable_socket(SOCKET *dest, InheritableSocket *src);
***************
*** 3606,3613 ****
  
  #ifdef WIN32
        param->PostmasterHandle = PostmasterHandle;
!       write_duplicated_handle(&param->initial_signal_pipe,
!                                                       
pgwin32_create_signal_listener(childPid),
                                                        childProcess);
  #endif
  
--- 3606,3617 ----
  
  #ifdef WIN32
        param->PostmasterHandle = PostmasterHandle;
! 
!       /* Create signaling area for my child */
!       pgwin32_create_signaling_area(childPid);
!       write_duplicated_handles(N_SIGNALING_HANDLES, 
!                                                       
param->initial_signal_handles,
!                                                       
pgwin32_initial_signal_handles, 
                                                        childProcess);
  #endif
  
***************
*** 3626,3651 ****
  
  #ifdef WIN32
  /*
!  * Duplicate a handle for usage in a child process, and write the child
!  * process instance of the handle to the parameter file.
   */
  static void
! write_duplicated_handle(HANDLE *dest, HANDLE src, HANDLE childProcess)
  {
!       HANDLE hChild = INVALID_HANDLE_VALUE;
  
!       if (!DuplicateHandle(GetCurrentProcess(),
!                                                src,
!                                                childProcess,
!                                                &hChild,
!                                                0,
!                                                TRUE,
!                                                DUPLICATE_CLOSE_SOURCE | 
DUPLICATE_SAME_ACCESS))
!               ereport(ERROR,
!                               (errmsg_internal("could not duplicate handle to 
be written to backend parameter file: error code %d",
!                                                                (int) 
GetLastError())));
  
!       *dest = hChild;
  }
  
  /*
--- 3630,3667 ----
  
  #ifdef WIN32
  /*
!  * Duplicate handles for usage in a child process, and write the child
!  * process instance of the handles to the parameter file.
   */
  static void
! write_duplicated_handles(int num, HANDLE *dest, HANDLE *src, HANDLE 
childProcess)
  {
!       int             i, j;
!       HANDLE  hChild;
  
!       for (i = 0; i < num; i++)
!       {
!               hChild = INVALID_HANDLE_VALUE;
!               
!               if (!DuplicateHandle(GetCurrentProcess(),
!                                                        src[i],
!                                                        childProcess,
!                                                        &hChild,
!                                                        0,
!                                                        TRUE,
!                                                        DUPLICATE_CLOSE_SOURCE 
| DUPLICATE_SAME_ACCESS))
!               {
!                       /* close previousely duplicated handles */
!                       for (j = 0; j < i; j++)
!                               CloseHandle(dest[j]);
!                       
!                       ereport(ERROR,
!                                       (errmsg_internal("could not duplicate 
handle to be written to backend parameter file: error code %d",
!                                                                        (int) 
GetLastError())));
!               }
  
!               dest[i] = hChild;
!       }
  }
  
  /*
***************
*** 3808,3814 ****
  
  #ifdef WIN32
        PostmasterHandle = param->PostmasterHandle;
!       pgwin32_initial_signal_pipe = param->initial_signal_pipe;
  #endif
  
        memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
--- 3824,3832 ----
  
  #ifdef WIN32
        PostmasterHandle = param->PostmasterHandle;
!       memcpy(pgwin32_initial_signal_handles, 
!                       param->initial_signal_handles,
!                       sizeof(HANDLE) * N_SIGNALING_HANDLES);
  #endif
  
        memcpy(&syslogPipe, &param->syslogPipe, sizeof(syslogPipe));
Index: src/backend/port/win32/signal.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/port/win32/signal.c,v
retrieving revision 1.11
diff -c -r1.11 signal.c
*** src/backend/port/win32/signal.c     31 Dec 2004 22:00:37 -0000      1.11
--- src/backend/port/win32/signal.c     4 Jun 2005 13:04:49 -0000
***************
*** 14,43 ****
  #include "postgres.h"
  
  #include <libpq/pqsignal.h>
  
  
! /* 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;
  
  static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
  static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
  static int    pg_signal_mask;
  
- DLLIMPORT HANDLE pgwin32_signal_event;
- HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
- 
- 
- /* Signal handling thread function */
- static DWORD WINAPI pg_signal_thread(LPVOID param);
  static BOOL WINAPI pg_console_handler(DWORD dwCtrlType);
  
! /* Sleep function that can be interrupted by signals */
  void
  pgwin32_backend_usleep(long microsec)
  {
!       if (WaitForSingleObject(pgwin32_signal_event, (microsec < 500 ? 1 : 
(microsec + 500) / 1000)) == WAIT_OBJECT_0)
        {
                pgwin32_dispatch_queued_signals();
                errno = EINTR;
--- 14,74 ----
  #include "postgres.h"
  
  #include <libpq/pqsignal.h>
+ #include "miscadmin.h"
+ #include "utils/memutils.h"
  
+ /* Simplified error report for this module */
+ #define ereport_signal(elevel, msg)   \
+ do{   \
+       if (ErrorContext != NULL)       \
+               ereport((elevel), \
+                               (errmsg_internal("Win32 Singaling: %s: error 
code: %d", \
+                                               (msg), (int)GetLastError()))); \
+       else{   \
+               write_stderr("Win32 Signaling: %s\n", msg);     \
+               exit (-1);      \
+       }\
+ }while (0)
+ 
+ /* Lock/Unlock signal area primitives */
+ #define lock_signal_shmem()   \
+ do { \
+       if (WaitForSingleObject(MySignalShmem->mutex, INFINITE) != 
WAIT_OBJECT_0)       \
+               ereport_signal(ERROR, "failed to wait on signal mutex");        
\
+ }while(0)
+ 
+ #define unlock_signal_shmem() \
+ do{   \
+       if (!ReleaseMutex(MySignalShmem->mutex))        \
+               ereport_signal(ERROR, "failed to release signal mutex");        
\
+ }while(0)
  
! /* Signaling shared memory of current process */
! DLLIMPORT Win32SignalShmemStruct *MySignalShmem;
! 
! /* Array to save handles for child process */
! HANDLE pgwin32_initial_signal_handles[N_SIGNALING_HANDLES] = 
! {
!       /* shmem handle */      NULL,
!       /* mutex handle */      NULL,
!       /* event handle */      NULL
! };
  
  static pqsigfunc pg_signal_array[PG_SIGNAL_COUNT];
  static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
  static int    pg_signal_mask;
  
  static BOOL WINAPI pg_console_handler(DWORD dwCtrlType);
  
! /* 
!  * pgwin32_backend_usleep
!  *            Sleep function that can be interrupted by signals 
!  */
  void
  pgwin32_backend_usleep(long microsec)
  {
!       if (WaitForSingleObject(pgwin32_signal_event, (microsec < 500 ? 
!                                               1 : (microsec + 500) / 1000)) 
== WAIT_OBJECT_0)
        {
                pgwin32_dispatch_queued_signals();
                errno = EINTR;
***************
*** 45,101 ****
        }
  }
  
  
! /* 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;
  
!       /* Create the global event handle used to flag signals */
!       pgwin32_signal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
!       if (pgwin32_signal_event == NULL)
!               ereport(FATAL,
!                               (errmsg_internal("failed to create signal 
event: %d", (int) GetLastError())));
! 
!       /* Create thread for handling signals */
!       signal_thread_handle = CreateThread(NULL, 0, pg_signal_thread, NULL, 0, 
NULL);
!       if (signal_thread_handle == NULL)
!               ereport(FATAL,
!                       (errmsg_internal("failed to create signal handler 
thread")));
  
        /* Create console control handle to pick up Ctrl-C etc */
        if (!SetConsoleCtrlHandler(pg_console_handler, TRUE))
!               ereport(FATAL,
!                        (errmsg_internal("failed to set console control 
handler")));
  }
  
! 
! /* Dispatch all signals currently queued and not blocked
!  * Blocked signals are ignored, and will be fired at the time of
!  * the sigsetmask() call. */
  void
  pgwin32_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++)
                {
--- 76,229 ----
        }
  }
  
+ /* 
+  * pgwin32_create_signaling_area
+  *            Create the signal area for specified pid. If any step 
+  *            failed, the error level is set to ERROR only since 
+  *            postmaster will call it at process fork. Accordingly,
+  *            we have to cleanup opened handles to avoid leakage. 
+  */
+ #define cleanup_and_ereport(elevel, msg)      \
+ do{   \
+       if (shmem)      UnmapViewOfFile(shmem); \
+       if (hShmem)     CloseHandle(hShmem);    \
+       if (hEvent)     CloseHandle(hEvent);    \
+       if (hMutex)     CloseHandle(hMutex);    \
+       \
+       ereport_signal((elevel), (msg));        \
+ } while (0)
+ 
+ void
+ pgwin32_create_signaling_area(pid_t pid)
+ {
+       char    name[64];
+       SECURITY_ATTRIBUTES sa;
+       HANDLE  hShmem, hMutex, hEvent;
+       Win32SignalShmemStruct *shmem;
+ 
+       shmem  = NULL;
+       hShmem = NULL;
+       hMutex = NULL;
+       hEvent = NULL;
+ 
+       ZeroMemory(&sa, sizeof(sa));
+       sa.nLength = sizeof(sa);
+       sa.bInheritHandle = TRUE;       
+ 
+       /* Create the global shared memory */ 
+       wsprintf(name, "%s.%d", SIGNAL_SHMEM_PREFIX, pid);
+       if (NULL == (hShmem = CreateFileMapping((HANDLE) 0xFFFFFFFF,
+                                                               &sa, 
PAGE_READWRITE,
+                                                               0L, 
sizeof(Win32SignalShmemStruct),
+                                                               name)))
+               cleanup_and_ereport(ERROR, 
+                                       "failed to create shared memory");
+       
+       if (NULL == (shmem = MapViewOfFile(hShmem,
+                                                       FILE_MAP_ALL_ACCESS,
+                                                       0, 0, 0)))
+               cleanup_and_ereport(ERROR, 
+                                       "failed to attach to signaling area");
+       
+       MemSet(shmem, 0, sizeof(Win32SignalShmemStruct));
+       
+       /* Create the global mutex */
+       wsprintf(name, "%s.%d", SIGNAL_MUTEX_PREFIX, pid);
+       if (NULL == (hMutex = CreateMutex(&sa, FALSE, name)))
+               cleanup_and_ereport(ERROR, 
+                                       "failed to create signal mutex");       
+ 
+       /* Create the global event */
+       wsprintf(name, "%s.%d", SIGNAL_EVENT_PREFIX, pid);
+       if (NULL == (hEvent = CreateEvent(&sa, TRUE, FALSE, name)))
+               cleanup_and_ereport(ERROR, 
+                                       "failed to create signal event");
+ 
+       /* 
+        * Only the postmater or standalone backend should save the
+        * handles in shared memory for its own use. For others, it
+        * is called by postmaster who create these handles for its 
+        * children, so save them in pgwin32_initial_signal_handles[]. 
+        */
+       if (pid == PostmasterPid || !IsPostmasterEnvironment)
+       {
+               shmem->mutex = hMutex;
+               shmem->event = hEvent;
+               MySignalShmem = shmem;
+       }
+       else
+       {
+               pgwin32_initial_signal_handles[0] = hShmem;
+               pgwin32_initial_signal_handles[1] = hMutex;
+               pgwin32_initial_signal_handles[2] = hEvent;
+       }
+ }
  
! /* 
!  * pgwin32_signal_initialize
!  *            Allocate and initialize signal emulation shared memory, 
!  *            including a mutex protecting the whole area, an event 
!  *            notifying that a signal was sent to current process, and 
!  *            a queue saving signals. All of them are in global namespace. 
!  */
  void
  pgwin32_signal_initialize(void)
  {
        int                     i;
  
+       /* Initialize the local part */
        for (i = 0; i < PG_SIGNAL_COUNT; i++)
        {
                pg_signal_array[i] = SIG_DFL;
                pg_signal_defaults[i] = SIG_IGN;
        }
        pg_signal_mask = 0;
  
!       /* Initialize the shared memory part */
!       if (pgwin32_initial_signal_handles[0] != NULL)
!       {
!               /* Use the postmaster created shared memory */
!               if (NULL == (MySignalShmem = MapViewOfFile(
!                                                               
pgwin32_initial_signal_handles[0], 
!                                                               
FILE_MAP_ALL_ACCESS, 
!                                                               0, 0, 0)))
!                       ereport_signal(FATAL, 
!                                               "failed to attach to signal 
area");
! 
!               MySignalShmem->mutex = pgwin32_initial_signal_handles[1];
!               MySignalShmem->event = pgwin32_initial_signal_handles[2];
! 
!               /*
!                * Don't dispatch any signals for now, since the signal 
!                * handlers are not set up yet.
!                */
!       }
!       else
!               /* Create the singaling area for myself */
!               pgwin32_create_signaling_area(GetCurrentProcessId());
  
        /* Create console control handle to pick up Ctrl-C etc */
        if (!SetConsoleCtrlHandler(pg_console_handler, TRUE))
!               ereport_signal(FATAL, 
!                                       "failed to set console control");       
  }
  
! /* 
!  * pgwin32_dispatch_queued_signals
!  *            Dispatch all signals currently queued and not blocked
!  *            Blocked signals are ignored, and will be fired at the 
!  *      time of the sigsetmask() call. 
!  */
  void
  pgwin32_dispatch_queued_signals(void)
  {
        int                     i;
  
!       lock_signal_shmem();
!       while (MySignalShmem->queue & ~pg_signal_mask)
        {
                /* One or more unblocked signals queued for execution */
!               int     exec_mask = MySignalShmem->queue & ~pg_signal_mask;
  
                for (i = 0; i < PG_SIGNAL_COUNT; i++)
                {
***************
*** 106,117 ****
  
                                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 */
--- 234,245 ----
  
                                if (sig == SIG_DFL)
                                        sig = pg_signal_defaults[i];
!                               MySignalShmem->queue &= ~sigmask(i);
                                if (sig != SIG_ERR && sig != SIG_IGN && sig != 
SIG_DFL)
                                {
!                                       unlock_signal_shmem();
                                        sig(i);
!                                       lock_signal_shmem();
                                        break;          /* Restart outer loop, 
in case signal mask
                                                                 * or queue has 
been modified inside
                                                                 * signal 
handler */
***************
*** 119,129 ****
                        }
                }
        }
!       ResetEvent(pgwin32_signal_event);
!       LeaveCriticalSection(&pg_signal_crit_sec);
  }
  
! /* signal masking. Only called on main thread, no sync required */
  int
  pqsigsetmask(int mask)
  {
--- 247,263 ----
                        }
                }
        }
!       unlock_signal_shmem();
!       
!       if (!ResetEvent(MySignalShmem->event))
!               ereport_signal(ERROR, 
!                               "failed to reset signal waiting event");        
  }
  
! /* 
!  * pqsigsetmask
!  *            Signal masking emulation in win32. 
!  */
  int
  pqsigsetmask(int mask)
  {
***************
*** 141,148 ****
        return prevmask;
  }
  
! 
! /* signal manipulation. Only called on main thread, no sync required */
  pqsigfunc
  pqsignal(int signum, pqsigfunc handler)
  {
--- 275,284 ----
        return prevmask;
  }
  
! /* 
!  * pqsignal
!  *            Function signal() emulation in win32
!  */
  pqsigfunc
  pqsignal(int signum, pqsigfunc handler)
  {
***************
*** 155,286 ****
        return prevfunc;
  }
  
! /* Create the signal listener pipe for specified pid */
! HANDLE
! pgwin32_create_signal_listener(pid_t pid)
! {
!       char            pipename[128];
!       HANDLE          pipe;
! 
!       wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", (int) pid);
! 
!       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)
!               ereport(ERROR,
!                               (errmsg("could not create signal listener pipe 
for pid %d: error code %d",
!                                               (int) pid, (int) 
GetLastError())));
! 
!       return pipe;
! }
! 
! 
! /*
!  * 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!
   */
- 
- 
  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);
! 
!       SetEvent(pgwin32_signal_event);
! }
! 
! /* 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 = pgwin32_initial_signal_pipe;
! 
!       wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", GetCurrentProcessId());
! 
!       for (;;)
!       {
!               BOOL            fConnected;
!               HANDLE          hThread;
! 
!               if (pipe == INVALID_HANDLE_VALUE)
!               {
!                       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)
!                       {
!                               write_stderr("could not create signal listener 
pipe: error code %d; retrying\n", (int) GetLastError());
!                               SleepEx(500, FALSE);
!                               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)
!                               write_stderr("could not create signal dispatch 
thread: error code %d\n",
!                                                        (int) GetLastError());
!                       else
!                               CloseHandle(hThread);
!               }
!               else
!                       /* Connection failed. Cleanup and try again */
!                       CloseHandle(pipe);
! 
!               /* Set up so we create a new pipe on next loop */
!               pipe = INVALID_HANDLE_VALUE;
!       }
!       return 0;
  }
  
! 
! /* Console control handler will execute on a thread created
!    by the OS at the time of invocation */
  static BOOL WINAPI
  pg_console_handler(DWORD dwCtrlType)
  {
--- 291,320 ----
        return prevfunc;
  }
  
! /* 
!  * pg_queue_signal
!  *            Trigger a signal handling of current process
   */
  void
  pg_queue_signal(int signum)
  {
        if (signum >= PG_SIGNAL_COUNT || signum <= 0)
                return;
  
!       lock_signal_shmem();
!       MySignalShmem->queue |= sigmask(signum);
!       unlock_signal_shmem();
! 
!       if (!SetEvent(MySignalShmem->event))
!               ereport_signal(ERROR, 
!                               "failed to set signal waiting event");  
  }
  
! /* 
!  * pg_console_handler
!  *            Console control handler will execute on a thread created
!  *            by the OS at the time of invocation 
!  */
  static BOOL WINAPI
  pg_console_handler(DWORD dwCtrlType)
  {
Index: src/include/port/win32.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/port/win32.h,v
retrieving revision 1.45
diff -c -r1.45 win32.h
*** src/include/port/win32.h    20 May 2005 14:53:26 -0000      1.45
--- src/include/port/win32.h    4 Jun 2005 11:55:36 -0000
***************
*** 144,149 ****
--- 144,164 ----
  #define SIGUSR1                               30
  #define SIGUSR2                               31
  
+ /* Number of signaling handles */
+ #define N_SIGNALING_HANDLES           3
+ 
+ /* Signaling variables name prefix */
+ #define SIGNAL_SHMEM_PREFIX           "Global\\PostgreSQL.SignalShmem"
+ #define SIGNAL_MUTEX_PREFIX           "Global\\PostgreSQL.SignalMutex"
+ #define SIGNAL_EVENT_PREFIX           "Global\\PostgreSQL.SignalEvent"
+ 
+ /* Signaling shared memory structure */
+ typedef struct Win32SignalShmemStruct{
+       HANDLE  mutex;
+       HANDLE  event;
+       int             queue;
+ }Win32SignalShmemStruct;
+ 
  struct timezone
  {
        int                     tz_minuteswest; /* Minutes west of GMT.  */
***************
*** 212,225 ****
  
  
  /* In backend/port/win32/signal.c */
- extern DLLIMPORT HANDLE pgwin32_signal_event;
- extern HANDLE pgwin32_initial_signal_pipe;
- 
  void          pgwin32_signal_initialize(void);
! HANDLE                pgwin32_create_signal_listener(pid_t pid);
  void          pgwin32_dispatch_queued_signals(void);
  void          pg_queue_signal(int signum);
  
  #ifndef FRONTEND
  #define pg_usleep(t) pgwin32_backend_usleep(t)
  void          pgwin32_backend_usleep(long microsec);
--- 227,242 ----
  
  
  /* In backend/port/win32/signal.c */
  void          pgwin32_signal_initialize(void);
! void          pgwin32_create_signaling_area(pid_t pid);
  void          pgwin32_dispatch_queued_signals(void);
  void          pg_queue_signal(int signum);
  
+ extern DLLIMPORT Win32SignalShmemStruct       *MySignalShmem;
+ extern HANDLE pgwin32_initial_signal_handles[N_SIGNALING_HANDLES];
+ 
+ #define pgwin32_signal_event  (MySignalShmem->event)
+ 
  #ifndef FRONTEND
  #define pg_usleep(t) pgwin32_backend_usleep(t)
  void          pgwin32_backend_usleep(long microsec);
---------------------------(end of broadcast)---------------------------
TIP 5: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to