Natoli and Bruce Momjian (and some cosmetic fixes from Neil Conway).
Changes:
- remove duplicate signal definitions from pqsignal.h
- replace pqkill() with kill() and redefine kill() in Win32
- use ereport() in place of fprintf() in some error handling in
pqsignal.c
- export pg_queue_signal() and make use of it where necessary
- add a console control handler for Ctrl-C and similar handling
on Win32
- do WaitForSingleObjectEx() in CHECK_FOR_INTERRUPTS() on Win32;
query cancelling should now work on Win32
- various other fixes and cleanups
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.108 2004/01/27 00:45:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.109 2004/02/08 22:28:56 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#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"
* 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 (pqkill(listenerPID, SIGUSR2) < 0)
+ if (kill(listenerPID, SIGUSR2) < 0)
{
/*
* Get rid of pg_listener entry if it refers to a PID that
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.30 2004/01/27 00:46:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.31 2004/02/08 22:28:56 neilc Exp $
*
* NOTES
* This shouldn't be in libpq, but the monitor and some other
* 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"
/* Signal handling thread function */
static DWORD WINAPI pg_signal_thread(LPVOID param);
+static BOOL WINAPI pg_console_handler(DWORD dwCtrlType);
/* Initialization */
void
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);
- }
-
+ 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)
- {
- fprintf(stderr, gettext("Failed to create signal handler thread!\n"));
- exit(1);
- }
+ 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!")));
}
*/
-static void
+void
pg_queue_signal(int signum)
{
if (signum >= PG_SIGNAL_COUNT || signum < 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) {
+ printf("Console handler being called!\n");
+ fflush(stdout);
+ 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
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/sysv_sema.c,v 1.13 2004/01/27 00:45:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/port/sysv_sema.c,v 1.14 2004/02/08 22:28:56 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/pg_sema.h"
-#include "libpq/pqsignal.h"
#ifndef HAVE_UNION_SEMUN
continue; /* oops, GETPID failed */
if (creatorPID != getpid())
{
- if (pqkill(creatorPID, 0) == 0 ||
- errno != ESRCH)
+ if (kill(creatorPID, 0) == 0 || errno != ESRCH)
continue; /* sema belongs to a live process */
}
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.30 2004/02/02 00:11:31 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/port/sysv_shmem.c,v 1.31 2004/02/08 22:28:56 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#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) */
hdr = (PGShmemHeader *) memAddress;
if (hdr->creatorPID != getpid())
{
- if (pqkill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
+ if (kill(hdr->creatorPID, 0) == 0 || errno != ESRCH)
{
shmdt(memAddress);
continue; /* segment belongs to a live process */
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.364 2004/01/28 21:02:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.365 2004/02/08 22:28:56 neilc Exp $
*
* NOTES
*
static void win32_AddChild(pid_t pid, HANDLE handle);
static void win32_RemoveChild(pid_t pid);
static pid_t win32_waitpid(int *exitstatus);
+static DWORD WINAPI win32_sigchld_waiter(LPVOID param);
static pid_t *win32_childPIDArray;
static HANDLE *win32_childHNDArray;
/* FIXME: [fork/exec] Ideally, we would resize these arrays with changes
* in MaxBackends, but this'll do as a first order solution.
*/
- win32_childPIDArray = (HANDLE*)malloc(NUM_BACKENDARRAY_ELEMS*sizeof(pid_t));
+ win32_childPIDArray = (pid_t*)malloc(NUM_BACKENDARRAY_ELEMS*sizeof(pid_t));
win32_childHNDArray = (HANDLE*)malloc(NUM_BACKENDARRAY_ELEMS*sizeof(HANDLE));
if (!win32_childPIDArray || !win32_childHNDArray)
ereport(LOG,
ereport(DEBUG2,
(errmsg_internal("processing cancel request: sending SIGINT to process %d",
backendPID)));
- pqkill(bp->pid, SIGINT);
+ kill(bp->pid, SIGINT);
}
else
/* Right PID, wrong key: no way, Jose */
* will start a new one with a possibly changed config
*/
if (BgWriterPID != 0)
- pqkill(BgWriterPID, SIGTERM);
+ kill(BgWriterPID, SIGTERM);
}
PG_SETMASK(&UnBlockSig);
* Wait for children to end their work and ShutdownDataBase.
*/
if (BgWriterPID != 0)
- pqkill(BgWriterPID, SIGTERM);
+ kill(BgWriterPID, SIGTERM);
if (Shutdown >= SmartShutdown)
break;
Shutdown = SmartShutdown;
* and exit) and ShutdownDataBase when they are gone.
*/
if (BgWriterPID != 0)
- pqkill(BgWriterPID, SIGTERM);
+ kill(BgWriterPID, SIGTERM);
if (Shutdown >= FastShutdown)
break;
ereport(LOG,
* properly shutdown data base system.
*/
if (BgWriterPID != 0)
- pqkill(BgWriterPID, SIGQUIT);
+ kill(BgWriterPID, SIGQUIT);
ereport(LOG,
(errmsg("received immediate shutdown request")));
if (ShutdownPID > 0)
- pqkill(ShutdownPID, SIGQUIT);
+ kill(ShutdownPID, SIGQUIT);
if (StartupPID > 0)
- pqkill(StartupPID, SIGQUIT);
+ kill(StartupPID, SIGQUIT);
if (DLGetHead(BackendList))
SignalChildren(SIGQUIT);
ExitPostmaster(0);
(errmsg_internal("sending %s to process %d",
(SendStop ? "SIGSTOP" : "SIGQUIT"),
(int) bp->pid)));
- pqkill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT));
+ kill(bp->pid, (SendStop ? SIGSTOP : SIGQUIT));
}
}
else
(errmsg_internal("sending signal %d to process %d",
signal,
(int) bp->pid)));
- pqkill(bp->pid, signal);
+ kill(bp->pid, signal);
}
curr = next;
char *p;
int i;
char cmdLine[MAXPGPATH];
+ HANDLE childHandleCopy;
+ HANDLE waiterThread;
/* Format the cmd line */
snprintf(cmdLine,sizeof(cmdLine),"%s",path);
if (!IsUnderPostmaster)
/* We are the Postmaster creating a child... */
win32_AddChild(pi.dwProcessId,pi.hProcess);
- else
+
+ if (!DuplicateHandle(GetCurrentProcess(),
+ pi.hProcess,
+ GetCurrentProcess(),
+ &childHandleCopy,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS))
+ ereport(FATAL,
+ (errmsg_internal("failed to duplicate child handle: %i",GetLastError())));
+ waiterThread = CreateThread(NULL, 64*1024, win32_sigchld_waiter, (LPVOID)childHandleCopy, 0, NULL);
+ if (!waiterThread)
+ ereport(FATAL,
+ (errmsg_internal("failed to create sigchld waiter thread: %i",GetLastError())));
+ CloseHandle(waiterThread);
+
+ if (IsUnderPostmaster)
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
/* Swap last entry into the "removed" one */
--win32_numChildren;
- win32_childPIDArray[win32_numChildren] = win32_childPIDArray[i];
- win32_childHNDArray[win32_numChildren] = win32_childHNDArray[i];
+ win32_childPIDArray[i] = win32_childPIDArray[win32_numChildren];
+ win32_childHNDArray[i] = win32_childHNDArray[win32_numChildren];
return;
}
}
{
case WAIT_FAILED:
ereport(ERROR,
- (errmsg_internal("failed to wait on %d children",
- win32_numChildren)));
+ (errmsg_internal("failed to wait on %d children: %i",
+ win32_numChildren,GetLastError())));
/* Fall through to WAIT_TIMEOUTs return */
case WAIT_TIMEOUT:
return -1;
}
+/* Note! Code belows executes on separate threads, one for
+ each child process created */
+static DWORD WINAPI win32_sigchld_waiter(LPVOID param) {
+ HANDLE procHandle = (HANDLE)param;
+
+ DWORD r = WaitForSingleObject(procHandle, INFINITE);
+ if (r == WAIT_OBJECT_0)
+ pg_queue_signal(SIGCHLD);
+ else
+ fprintf(stderr,"ERROR: Failed to wait on child process handle: %i\n",GetLastError());
+ CloseHandle(procHandle);
+ return 0;
+}
+
#endif
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.12 2004/01/27 00:45:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.13 2004/02/08 22:28:56 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#include "miscadmin.h"
#include "storage/pmsignal.h"
#include "storage/shmem.h"
-#include "libpq/pqsignal.h"
/*
/* Atomically set the proper flag */
PMSignalFlags[reason] = true;
/* Send signal to postmaster */
- pqkill(PostmasterPid, SIGUSR1);
+ kill(PostmasterPid, SIGUSR1);
}
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.145 2004/01/27 00:45:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.146 2004/02/08 22:28:56 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#include "storage/proc.h"
#include "storage/sinval.h"
#include "storage/spin.h"
-#include "libpq/pqsignal.h"
/* GUC variables */
int DeadlockTimeout = 1000;
{
/* Time to die */
statement_timeout_active = false;
- pqkill(MyProcPid, SIGINT);
+ kill(MyProcPid, SIGINT);
}
else
{
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.121 2004/01/27 00:45:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.122 2004/02/08 22:28:57 neilc Exp $
*
*-------------------------------------------------------------------------
*/
#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"
*/
if (other_pid != my_pid)
{
- if (pqkill(other_pid, 0) == 0 ||
+ if (kill(other_pid, 0) == 0 ||
(errno != ESRCH
#ifdef __BEOS__
&& errno != EINVAL
* 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.24 2004/01/27 00:45:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/libpq/pqsignal.h,v 1.25 2004/02/08 22:28:57 neilc Exp $
*
* NOTES
* This shouldn't be in libpq, but the monitor and some other
#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,
BlockSig,
BlockSig,
AuthBlockSig;
-#define PG_SETMASK(mask) pqsigsetmask(*((int*)(mask)))
+#ifndef WIN32
+#define PG_SETMASK(mask) sigsetmask(*((int*)(mask)))
+#else
+#define PG_SETMASK(mask) pqsigsetmask(*((int*)(mask)))
+int pqsigsetmask(int mask);
+#endif
#endif
typedef void (*pqsigfunc) (int);
extern void pqinitmask(void);
extern pqsigfunc pqsignal(int signo, pqsigfunc func);
+extern void pg_queue_signal(int signum);
#ifdef WIN32
#define sigmask(sig) ( 1 << (sig-1) )
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 */
-
+/* Signal function return values */
#undef SIG_DFL
#undef SIG_ERR
#undef SIG_IGN
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.151 2004/02/06 19:36:18 wieck Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.152 2004/02/08 22:28:57 neilc Exp $
*
* NOTES
* some of the information in this file should be moved to
/* in postgres.c */
extern void ProcessInterrupts(void);
+#ifndef WIN32
#define CHECK_FOR_INTERRUPTS() \
do { \
if (InterruptPending) \
ProcessInterrupts(); \
} while(0)
+#else
+#define CHECK_FOR_INTERRUPTS() \
+do { \
+ WaitForSingleObjectEx(GetCurrentThread(),0,TRUE); \
+ if (InterruptPending) \
+ ProcessInterrupts(); \
+} while (0)
+#endif
+
#define HOLD_INTERRUPTS() (InterruptHoldoffCount++)
-/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.16 2004/01/26 22:59:54 momjian Exp $ */
+/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.17 2004/02/08 22:28:57 neilc Exp $ */
/* undefine and redefine after #include */
#undef mkdir
#undef ERROR
#include <windows.h>
+#include <winsock.h>
#undef near
/* Must be here to avoid conflicting with prototype in windows.h */
#define sleep(sec) (Sleep(sec * 1000), /* no return value */ 0)
+
+#ifndef FRONTEND
+/* In libpq/pqsignal.c */
+#define kill(pid,sig) pqkill(pid,sig)
+int pqkill(int pid, int sig);
+#endif
+
/* Some extra signals */
#define SIGHUP 1
#define SIGQUIT 3