Commit 0021ae06 authored by Tom Lane's avatar Tom Lane

Fix Win32 problems with signals and sockets, by making the forkexec code

even uglier than it was already :-(.  Also, on Windows only, use temporary
shared memory segments instead of ordinary files to pass over critical
variable values from postmaster to child processes.  Magnus Hagander
parent e1bf6527
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/main/main.c,v 1.92 2004/11/05 17:11:17 petere Exp $ * $PostgreSQL: pgsql/src/backend/main/main.c,v 1.93 2004/11/17 00:14:09 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -118,9 +118,6 @@ main(int argc, char *argv[]) ...@@ -118,9 +118,6 @@ main(int argc, char *argv[])
argv[0], err); argv[0], err);
exit(1); exit(1);
} }
/* Start our win32 signal implementation */
pgwin32_signal_initialize();
} }
#endif #endif
...@@ -281,6 +278,16 @@ main(int argc, char *argv[]) ...@@ -281,6 +278,16 @@ main(int argc, char *argv[])
exit(SubPostmasterMain(argc, argv)); exit(SubPostmasterMain(argc, argv));
#endif #endif
#ifdef WIN32
/*
* Start our win32 signal implementation
*
* SubPostmasterMain() will do this for itself, but the remaining
* modes need it here
*/
pgwin32_signal_initialize();
#endif
/* /*
* If the first argument is "-boot", then invoke bootstrap mode. (This * If the first argument is "-boot", then invoke bootstrap mode. (This
* path is taken only for a standalone bootstrap process.) * path is taken only for a standalone bootstrap process.)
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.9 2004/11/09 13:01:25 petere Exp $ * $PostgreSQL: pgsql/src/backend/port/win32/signal.c,v 1.10 2004/11/17 00:14:10 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -26,6 +26,7 @@ static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT]; ...@@ -26,6 +26,7 @@ static pqsigfunc pg_signal_defaults[PG_SIGNAL_COUNT];
static int pg_signal_mask; static int pg_signal_mask;
DLLIMPORT HANDLE pgwin32_signal_event; DLLIMPORT HANDLE pgwin32_signal_event;
HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
/* Signal handling thread function */ /* Signal handling thread function */
...@@ -154,6 +155,28 @@ pqsignal(int signum, pqsigfunc handler) ...@@ -154,6 +155,28 @@ pqsignal(int signum, pqsigfunc handler)
return prevfunc; 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 * All functions below execute on the signal handler thread
* and must be synchronized as such! * and must be synchronized as such!
...@@ -210,7 +233,7 @@ static DWORD WINAPI ...@@ -210,7 +233,7 @@ static DWORD WINAPI
pg_signal_thread(LPVOID param) pg_signal_thread(LPVOID param)
{ {
char pipename[128]; char pipename[128];
HANDLE pipe = INVALID_HANDLE_VALUE; HANDLE pipe = pgwin32_initial_signal_pipe;
wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", GetCurrentProcessId()); wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", GetCurrentProcessId());
...@@ -219,15 +242,19 @@ pg_signal_thread(LPVOID param) ...@@ -219,15 +242,19 @@ pg_signal_thread(LPVOID param)
BOOL fConnected; BOOL fConnected;
HANDLE hThread; HANDLE hThread;
if (pipe == INVALID_HANDLE_VALUE)
{
pipe = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX, pipe = CreateNamedPipe(pipename, PIPE_ACCESS_DUPLEX,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL); PIPE_UNLIMITED_INSTANCES, 16, 16, 1000, NULL);
if (pipe == INVALID_HANDLE_VALUE) if (pipe == INVALID_HANDLE_VALUE)
{ {
write_stderr("could not create signal listener pipe: error code %d; retrying\n", (int) GetLastError()); write_stderr("could not create signal listener pipe: error code %d; retrying\n", (int) GetLastError());
SleepEx(500, FALSE); SleepEx(500, FALSE);
continue; continue;
} }
}
fConnected = ConnectNamedPipe(pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED); fConnected = ConnectNamedPipe(pipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
if (fConnected) if (fConnected)
...@@ -244,6 +271,9 @@ pg_signal_thread(LPVOID param) ...@@ -244,6 +271,9 @@ pg_signal_thread(LPVOID param)
else else
/* Connection failed. Cleanup and try again */ /* Connection failed. Cleanup and try again */
CloseHandle(pipe); CloseHandle(pipe);
/* Set up so we create a new pipe on next loop */
pipe = INVALID_HANDLE_VALUE;
} }
return 0; return 0;
} }
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2004, PostgreSQL Global Development Group * Copyright (c) 2001-2004, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.84 2004/10/28 01:38:41 neilc Exp $ * $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.85 2004/11/17 00:14:12 tgl Exp $
* ---------- * ----------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -110,8 +110,9 @@ bool pgstat_collect_blocklevel = false; ...@@ -110,8 +110,9 @@ bool pgstat_collect_blocklevel = false;
* ---------- * ----------
*/ */
NON_EXEC_STATIC int pgStatSock = -1; NON_EXEC_STATIC int pgStatSock = -1;
static int pgStatPipe[2]; NON_EXEC_STATIC int pgStatPipe[2] = {-1,-1};
static struct sockaddr_storage pgStatAddr; static struct sockaddr_storage pgStatAddr;
static pid_t pgStatCollectorPid = 0;
static time_t last_pgstat_start_time; static time_t last_pgstat_start_time;
...@@ -492,10 +493,6 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType) ...@@ -492,10 +493,6 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
/* postgres_exec_path is not passed by write_backend_variables */ /* postgres_exec_path is not passed by write_backend_variables */
av[ac++] = postgres_exec_path; av[ac++] = postgres_exec_path;
/* Pipe file ids (those not passed by write_backend_variables) */
snprintf(pgstatBuf[bufc++], 32, "%d", pgStatPipe[0]);
snprintf(pgstatBuf[bufc++], 32, "%d", pgStatPipe[1]);
/* Add to the arg list */ /* Add to the arg list */
Assert(bufc <= lengthof(pgstatBuf)); Assert(bufc <= lengthof(pgstatBuf));
for (i = 0; i < bufc; i++) for (i = 0; i < bufc; i++)
...@@ -517,12 +514,10 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType) ...@@ -517,12 +514,10 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
static void static void
pgstat_parseArgs(int argc, char *argv[]) pgstat_parseArgs(int argc, char *argv[])
{ {
Assert(argc == 6); Assert(argc == 4);
argc = 3; argc = 3;
StrNCpy(postgres_exec_path, argv[argc++], MAXPGPATH); StrNCpy(postgres_exec_path, argv[argc++], MAXPGPATH);
pgStatPipe[0] = atoi(argv[argc++]);
pgStatPipe[1] = atoi(argv[argc++]);
} }
#endif /* EXEC_BACKEND */ #endif /* EXEC_BACKEND */
...@@ -1385,12 +1380,13 @@ PgstatBufferMain(int argc, char *argv[]) ...@@ -1385,12 +1380,13 @@ PgstatBufferMain(int argc, char *argv[])
(errcode_for_socket_access(), (errcode_for_socket_access(),
errmsg("could not create pipe for statistics buffer: %m"))); errmsg("could not create pipe for statistics buffer: %m")));
#ifdef EXEC_BACKEND
/* child becomes collector process */ /* child becomes collector process */
switch (pgstat_forkexec(STAT_PROC_COLLECTOR)) #ifdef EXEC_BACKEND
pgStatCollectorPid = pgstat_forkexec(STAT_PROC_COLLECTOR);
#else #else
switch (fork()) pgStatCollectorPid = fork();
#endif #endif
switch (pgStatCollectorPid)
{ {
case -1: case -1:
ereport(ERROR, ereport(ERROR,
...@@ -1445,7 +1441,12 @@ PgstatCollectorMain(int argc, char *argv[]) ...@@ -1445,7 +1441,12 @@ PgstatCollectorMain(int argc, char *argv[])
pqsignal(SIGHUP, SIG_IGN); pqsignal(SIGHUP, SIG_IGN);
pqsignal(SIGINT, SIG_IGN); pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGTERM, SIG_IGN); pqsignal(SIGTERM, SIG_IGN);
#ifndef WIN32
pqsignal(SIGQUIT, SIG_IGN); pqsignal(SIGQUIT, SIG_IGN);
#else
/* kluge to allow buffer process to kill collector; FIXME */
pqsignal(SIGQUIT, pgstat_exit);
#endif
pqsignal(SIGALRM, SIG_IGN); pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN); pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, SIG_IGN); pqsignal(SIGUSR1, SIG_IGN);
...@@ -1943,6 +1944,16 @@ pgstat_exit(SIGNAL_ARGS) ...@@ -1943,6 +1944,16 @@ pgstat_exit(SIGNAL_ARGS)
* be cleaner to allow any pending messages to be sent, but that * be cleaner to allow any pending messages to be sent, but that
* creates a tradeoff against speed of exit. * creates a tradeoff against speed of exit.
*/ */
/*
* If running in bufferer, kill our collector as well. On some broken
* win32 systems, it does not shut down automatically because of issues
* with socket inheritance. XXX so why not fix the socket inheritance...
*/
#ifdef WIN32
if (pgStatCollectorPid > 0)
kill(pgStatCollectorPid, SIGQUIT);
#endif
exit(0); exit(0);
} }
......
This diff is collapsed.
/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.39 2004/10/06 17:47:53 momjian Exp $ */ /* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.40 2004/11/17 00:14:14 tgl Exp $ */
/* undefine and redefine after #include */ /* undefine and redefine after #include */
#undef mkdir #undef mkdir
...@@ -104,8 +104,11 @@ int semop(int semId, struct sembuf * sops, int flag); ...@@ -104,8 +104,11 @@ int semop(int semId, struct sembuf * sops, int flag);
/* In backend/port/win32/signal.c */ /* In backend/port/win32/signal.c */
void pgwin32_signal_initialize(void);
extern DLLIMPORT HANDLE pgwin32_signal_event; 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 pgwin32_dispatch_queued_signals(void);
void pg_queue_signal(int signum); void pg_queue_signal(int signum);
......
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