aboutsummaryrefslogtreecommitdiff
path: root/src/backend/libpq/pqsignal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/libpq/pqsignal.c')
-rw-r--r--src/backend/libpq/pqsignal.c295
1 files changed, 4 insertions, 291 deletions
diff --git a/src/backend/libpq/pqsignal.c b/src/backend/libpq/pqsignal.c
index 34e5883797e..dc1f6ccc087 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.32 2004/02/18 16:25:12 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.33 2004/04/12 16:19:18 momjian Exp $
*
* NOTES
* This shouldn't be in libpq, but the monitor and some other
@@ -38,9 +38,6 @@
* is to do signal-handler reinstallation, which doesn't work well
* at all.
* ------------------------------------------------------------------------*/
-#ifdef WIN32
-#define _WIN32_WINNT 0x0400
-#endif
#include "postgres.h"
@@ -131,7 +128,9 @@ pqinitmask(void)
}
+/* Win32 signal handling is in backend/port/win32/signal.c */
#ifndef WIN32
+
/*
* Set up a signal handler
*/
@@ -154,290 +153,4 @@ 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);
-static BOOL WINAPI pg_console_handler(DWORD dwCtrlType);
-
-/* 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))
- ereport(FATAL,
- (errmsg_internal("Failed to get main thread handle!")));
-
- /* 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!")));
-
- 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. */
-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!
- */
-
-
-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;
-}
-
-
-/* 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) {
- if (dwCtrlType == CTRL_C_EVENT ||
- dwCtrlType == CTRL_BREAK_EVENT ||
- dwCtrlType == CTRL_CLOSE_EVENT ||
- dwCtrlType == CTRL_SHUTDOWN_EVENT) {
- pg_queue_signal(SIGINT);
- return TRUE;
- }
- return FALSE;
-}
-
-
-#endif
+#endif /* WIN32 */