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 @@
*
*
* 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[])
argv[0], err);
exit(1);
}
/* Start our win32 signal implementation */
pgwin32_signal_initialize();
}
#endif
......@@ -281,6 +278,16 @@ main(int argc, char *argv[])
exit(SubPostmasterMain(argc, argv));
#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
* path is taken only for a standalone bootstrap process.)
......
......@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
*
* 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];
static int pg_signal_mask;
DLLIMPORT HANDLE pgwin32_signal_event;
HANDLE pgwin32_initial_signal_pipe = INVALID_HANDLE_VALUE;
/* Signal handling thread function */
......@@ -154,6 +155,28 @@ pqsignal(int signum, pqsigfunc handler)
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!
......@@ -210,7 +233,7 @@ static DWORD WINAPI
pg_signal_thread(LPVOID param)
{
char pipename[128];
HANDLE pipe = INVALID_HANDLE_VALUE;
HANDLE pipe = pgwin32_initial_signal_pipe;
wsprintf(pipename, "\\\\.\\pipe\\pgsignal_%d", GetCurrentProcessId());
......@@ -219,14 +242,18 @@ pg_signal_thread(LPVOID param)
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)
{
write_stderr("could not create signal listener pipe: error code %d; retrying\n", (int) GetLastError());
SleepEx(500, FALSE);
continue;
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);
......@@ -244,6 +271,9 @@ pg_signal_thread(LPVOID param)
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;
}
......
......@@ -13,7 +13,7 @@
*
* 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"
......@@ -110,8 +110,9 @@ bool pgstat_collect_blocklevel = false;
* ----------
*/
NON_EXEC_STATIC int pgStatSock = -1;
static int pgStatPipe[2];
NON_EXEC_STATIC int pgStatPipe[2] = {-1,-1};
static struct sockaddr_storage pgStatAddr;
static pid_t pgStatCollectorPid = 0;
static time_t last_pgstat_start_time;
......@@ -492,10 +493,6 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
/* postgres_exec_path is not passed by write_backend_variables */
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 */
Assert(bufc <= lengthof(pgstatBuf));
for (i = 0; i < bufc; i++)
......@@ -517,12 +514,10 @@ pgstat_forkexec(STATS_PROCESS_TYPE procType)
static void
pgstat_parseArgs(int argc, char *argv[])
{
Assert(argc == 6);
Assert(argc == 4);
argc = 3;
StrNCpy(postgres_exec_path, argv[argc++], MAXPGPATH);
pgStatPipe[0] = atoi(argv[argc++]);
pgStatPipe[1] = atoi(argv[argc++]);
}
#endif /* EXEC_BACKEND */
......@@ -1385,12 +1380,13 @@ PgstatBufferMain(int argc, char *argv[])
(errcode_for_socket_access(),
errmsg("could not create pipe for statistics buffer: %m")));
#ifdef EXEC_BACKEND
/* child becomes collector process */
switch (pgstat_forkexec(STAT_PROC_COLLECTOR))
#ifdef EXEC_BACKEND
pgStatCollectorPid = pgstat_forkexec(STAT_PROC_COLLECTOR);
#else
switch (fork())
pgStatCollectorPid = fork();
#endif
switch (pgStatCollectorPid)
{
case -1:
ereport(ERROR,
......@@ -1445,7 +1441,12 @@ PgstatCollectorMain(int argc, char *argv[])
pqsignal(SIGHUP, SIG_IGN);
pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGTERM, SIG_IGN);
#ifndef WIN32
pqsignal(SIGQUIT, SIG_IGN);
#else
/* kluge to allow buffer process to kill collector; FIXME */
pqsignal(SIGQUIT, pgstat_exit);
#endif
pqsignal(SIGALRM, SIG_IGN);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, SIG_IGN);
......@@ -1943,6 +1944,16 @@ pgstat_exit(SIGNAL_ARGS)
* be cleaner to allow any pending messages to be sent, but that
* 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);
}
......
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 */
#undef mkdir
......@@ -104,8 +104,11 @@ int semop(int semId, struct sembuf * sops, int flag);
/* In backend/port/win32/signal.c */
void pgwin32_signal_initialize(void);
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);
......
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