Commit f06e7952 authored by Neil Conway's avatar Neil Conway

Win32 signals cleanup. Patch by Magnus Hagander, with input from Claudio

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
parent 04e82e50
......@@ -7,7 +7,7 @@
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -83,7 +83,6 @@
#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"
......@@ -498,7 +497,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 (pqkill(listenerPID, SIGUSR2) < 0)
if (kill(listenerPID, SIGUSR2) < 0)
{
/*
* Get rid of pg_listener entry if it refers to a PID that
......
......@@ -9,7 +9,7 @@
*
*
* 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
......@@ -39,17 +39,12 @@
* 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"
......@@ -180,6 +175,7 @@ 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
......@@ -202,18 +198,18 @@ pgwin32_signal_initialize(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!")));
}
......@@ -344,7 +340,7 @@ pg_signal_apc(ULONG_PTR param)
*/
static void
void
pg_queue_signal(int signum)
{
if (signum >= PG_SIGNAL_COUNT || signum < 0)
......@@ -430,4 +426,20 @@ pg_signal_thread(LPVOID param)
}
/* 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
......@@ -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.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 $
*
*-------------------------------------------------------------------------
*/
......@@ -31,7 +31,6 @@
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/pg_sema.h"
#include "libpq/pqsignal.h"
#ifndef HAVE_UNION_SEMUN
......@@ -233,8 +232,7 @@ IpcSemaphoreCreate(int numSems)
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 */
}
......
......@@ -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.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 $
*
*-------------------------------------------------------------------------
*/
......@@ -33,7 +33,6 @@
#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) */
......@@ -304,7 +303,7 @@ PGSharedMemoryCreate(uint32 size, bool makePrivate, int port)
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 */
......
......@@ -37,7 +37,7 @@
*
*
* 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
*
......@@ -308,6 +308,7 @@ pid_t win32_forkexec(const char* path, char *argv[]);
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;
......@@ -850,7 +851,7 @@ PostmasterMain(int argc, char *argv[])
/* 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,
......@@ -1566,7 +1567,7 @@ processCancelRequest(Port *port, void *pkt)
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 */
......@@ -1738,7 +1739,7 @@ SIGHUP_handler(SIGNAL_ARGS)
* will start a new one with a possibly changed config
*/
if (BgWriterPID != 0)
pqkill(BgWriterPID, SIGTERM);
kill(BgWriterPID, SIGTERM);
}
PG_SETMASK(&UnBlockSig);
......@@ -1772,7 +1773,7 @@ pmdie(SIGNAL_ARGS)
* Wait for children to end their work and ShutdownDataBase.
*/
if (BgWriterPID != 0)
pqkill(BgWriterPID, SIGTERM);
kill(BgWriterPID, SIGTERM);
if (Shutdown >= SmartShutdown)
break;
Shutdown = SmartShutdown;
......@@ -1806,7 +1807,7 @@ pmdie(SIGNAL_ARGS)
* and exit) and ShutdownDataBase when they are gone.
*/
if (BgWriterPID != 0)
pqkill(BgWriterPID, SIGTERM);
kill(BgWriterPID, SIGTERM);
if (Shutdown >= FastShutdown)
break;
ereport(LOG,
......@@ -1854,13 +1855,13 @@ pmdie(SIGNAL_ARGS)
* 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);
......@@ -2130,7 +2131,7 @@ CleanupProc(int pid,
(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
......@@ -2225,7 +2226,7 @@ SignalChildren(int signal)
(errmsg_internal("sending signal %d to process %d",
signal,
(int) bp->pid)));
pqkill(bp->pid, signal);
kill(bp->pid, signal);
}
curr = next;
......@@ -3491,6 +3492,8 @@ pid_t win32_forkexec(const char* path, char *argv[])
char *p;
int i;
char cmdLine[MAXPGPATH];
HANDLE childHandleCopy;
HANDLE waiterThread;
/* Format the cmd line */
snprintf(cmdLine,sizeof(cmdLine),"%s",path);
......@@ -3522,7 +3525,23 @@ pid_t win32_forkexec(const char* path, char *argv[])
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);
......@@ -3566,8 +3585,8 @@ static void win32_RemoveChild(pid_t pid)
/* 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;
}
}
......@@ -3597,8 +3616,8 @@ static pid_t win32_waitpid(int *exitstatus)
{
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:
......@@ -3626,4 +3645,18 @@ static pid_t win32_waitpid(int *exitstatus)
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
......@@ -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.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 $
*
*-------------------------------------------------------------------------
*/
......@@ -20,7 +20,6 @@
#include "miscadmin.h"
#include "storage/pmsignal.h"
#include "storage/shmem.h"
#include "libpq/pqsignal.h"
/*
......@@ -65,7 +64,7 @@ SendPostmasterSignal(PMSignalReason reason)
/* Atomically set the proper flag */
PMSignalFlags[reason] = true;
/* Send signal to postmaster */
pqkill(PostmasterPid, SIGUSR1);
kill(PostmasterPid, SIGUSR1);
}
/*
......
......@@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -51,7 +51,6 @@
#include "storage/proc.h"
#include "storage/sinval.h"
#include "storage/spin.h"
#include "libpq/pqsignal.h"
/* GUC variables */
int DeadlockTimeout = 1000;
......@@ -1131,7 +1130,7 @@ CheckStatementTimeout(void)
{
/* Time to die */
statement_timeout_active = false;
pqkill(MyProcPid, SIGINT);
kill(MyProcPid, SIGINT);
}
else
{
......
......@@ -8,7 +8,7 @@
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
......@@ -32,7 +32,6 @@
#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"
......@@ -532,7 +531,7 @@ CreateLockFile(const char *filename, bool amPostmaster,
*/
if (other_pid != my_pid)
{
if (pqkill(other_pid, 0) == 0 ||
if (kill(other_pid, 0) == 0 ||
(errno != ESRCH
#ifdef __BEOS__
&& errno != EINVAL
......
......@@ -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.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
......@@ -22,15 +22,6 @@
#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,
......@@ -42,7 +33,12 @@ extern int UnBlockSig,
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);
......@@ -50,6 +46,7 @@ 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) )
......@@ -58,105 +55,7 @@ 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 */
/* Signal function return values */
#undef SIG_DFL
#undef SIG_ERR
#undef SIG_IGN
......
......@@ -12,7 +12,7 @@
* 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
......@@ -74,11 +74,21 @@ extern volatile uint32 CritSectionCount;
/* 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 */
......@@ -100,6 +101,13 @@ int semop(int semId, struct sembuf * sops, int flag);
#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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment