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(¶m->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, ¶m->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, ¶m->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