[all] Removed call to getppid in SendPostmasterSignal, replacing with a

PostmasterPid variable, which gets set (early) in PostmasterMain
getppid would not be the postmaster?

[fork/exec] Implements processCancelRequest by keeping an array of

pid/cancel_key structs in shared mem

[fork/exec] Moves AttachSharedMemoryAndSemaphores call for backends into
SubPostmasterMain

[win32] Implements reaper/waitpid by keeping an arrays of children
pids,handles in postmaster local mem
      - this item is largely untested, for reasons which should be
obvious, but appears sound

[win32/all] Added extern for pgpipe in Win32 case, and changed the second
pipe call (which seems to have been missed earlier) to pgpipe

[win32] #define'd ftruncate to chsize in the Win32 case

[win32] PG_USLEEP for Win32 has a misplaced paren. Fixed.

[win32] DLLIMPORT handling for MingW case


Claudio Natoli
This commit is contained in:
Bruce Momjian 2004-01-26 22:59:54 +00:00
parent ede3b762a3
commit eec08b95e7
8 changed files with 266 additions and 40 deletions

View File

@ -13,7 +13,7 @@
*
* Copyright (c) 2001-2003, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.55 2004/01/26 22:54:56 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.56 2004/01/26 22:59:53 momjian Exp $
* ----------
*/
#include "postgres.h"
@ -147,7 +147,7 @@ static void pgstat_recv_resetcounter(PgStat_MsgResetcounter *msg, int len);
#define piperead(a,b,c) read(a,b,c)
#define pipewrite(a,b,c) write(a,b,c)
#else
/* pgpipe() is in /src/port */
extern int pgpipe(int handles[2]); /* pgpipe() is in /src/port */
#define piperead(a,b,c) recv(a,b,c,0)
#define pipewrite(a,b,c) send(a,b,c,0)
#endif
@ -322,7 +322,7 @@ pgstat_init(void)
/*
* Create the pipe that controls the statistics collector shutdown
*/
if (pipe(pgStatPmPipe) < 0)
if (pgpipe(pgStatPmPipe) < 0)
{
ereport(LOG,
(errcode_for_socket_access(),

View File

@ -37,7 +37,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.361 2004/01/26 22:54:56 momjian Exp $
* $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.362 2004/01/26 22:59:53 momjian Exp $
*
* NOTES
*
@ -141,6 +141,11 @@ typedef struct bkend
static Dllist *BackendList;
#ifdef EXEC_BACKEND
#define NUM_BACKENDARRAY_ELEMS (2*MaxBackends)
static Backend *ShmemBackendArray;
#endif
/* The socket number we are listening for connections on */
int PostPortNumber;
char *UnixSocketDir;
@ -299,6 +304,14 @@ __attribute__((format(printf, 1, 2)));
#ifdef EXEC_BACKEND
#ifdef WIN32
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 pid_t *win32_childPIDArray;
static HANDLE *win32_childHNDArray;
static unsigned long win32_numChildren = 0;
#endif
static pid_t Backend_forkexec(Port *port);
@ -306,6 +319,11 @@ static pid_t Backend_forkexec(Port *port);
static unsigned long tmpBackendFileNum = 0;
void read_backend_variables(unsigned long id, Port *port);
static bool write_backend_variables(Port *port);
size_t ShmemBackendArraySize(void);
void ShmemBackendArrayAllocation(void);
static void ShmemBackendArrayAdd(Backend *bn);
static void ShmemBackendArrayRemove(pid_t pid);
#endif
#define StartupDataBase() SSDataBase(BS_XLOG_STARTUP)
@ -430,7 +448,7 @@ PostmasterMain(int argc, char *argv[])
*/
umask((mode_t) 0077);
MyProcPid = getpid();
MyProcPid = PostmasterPid = getpid();
/*
* Fire up essential subsystems: memory management
@ -825,6 +843,21 @@ PostmasterMain(int argc, char *argv[])
*/
BackendList = DLNewList();
#ifdef WIN32
/*
* Initialize the child pid/HANDLE arrays
*/
/* 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_childHNDArray = (HANDLE*)malloc(NUM_BACKENDARRAY_ELEMS*sizeof(HANDLE));
if (!win32_childPIDArray || !win32_childHNDArray)
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
#endif
/*
* Record postmaster options. We delay this till now to avoid
* recording bogus options (eg, NBuffers too high for available
@ -1257,11 +1290,7 @@ ProcessStartupPacket(Port *port, bool SSLdone)
if (proto == CANCEL_REQUEST_CODE)
{
#ifdef EXEC_BACKEND
abort(); /* FIXME: [fork/exec] Whoops. Not handled... yet */
#else
processCancelRequest(port, buf);
#endif
return 127; /* XXX */
}
@ -1494,8 +1523,12 @@ processCancelRequest(Port *port, void *pkt)
CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
int backendPID;
long cancelAuthCode;
Dlelem *curr;
Backend *bp;
#ifndef EXEC_BACKEND
Dlelem *curr;
#else
int i;
#endif
backendPID = (int) ntohl(canc->backendPID);
cancelAuthCode = (long) ntohl(canc->cancelAuthCode);
@ -1514,16 +1547,17 @@ processCancelRequest(Port *port, void *pkt)
backendPID)));
return;
}
#ifdef EXEC_BACKEND
else
AttachSharedMemoryAndSemaphores();
#endif
/* See if we have a matching backend */
#ifndef EXEC_BACKEND
for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
{
bp = (Backend *) DLE_VAL(curr);
#else
for (i = 0; i < NUM_BACKENDARRAY_ELEMS; i++)
{
bp = (Backend*) &ShmemBackendArray[i];
#endif
if (bp->pid == backendPID)
{
if (bp->cancel_key == cancelAuthCode)
@ -1846,14 +1880,12 @@ reaper(SIGNAL_ARGS)
{
int save_errno = errno;
#ifdef WIN32
#warning fix waidpid for Win32
#else
#ifdef HAVE_WAITPID
int status; /* backend exit status */
#else
#ifndef WIN32
union wait status; /* backend exit status */
#endif
#endif
int exitstatus;
int pid; /* process id of dead backend */
@ -1867,9 +1899,21 @@ reaper(SIGNAL_ARGS)
{
exitstatus = status;
#else
#ifndef WIN32
while ((pid = wait3(&status, WNOHANG, NULL)) > 0)
{
exitstatus = status.w_status;
#else
while ((pid = win32_waitpid(&exitstatus)) > 0)
{
/*
* We need to do this here, and not in CleanupProc, since this
* is to be called on all children when we are done with them.
* Could move to LogChildExit, but that seems like asking for
* future trouble...
*/
win32_RemoveChild(pid);
#endif
#endif
/*
@ -1957,7 +2001,6 @@ reaper(SIGNAL_ARGS)
CleanupProc(pid, exitstatus);
} /* loop over pending child-death reports */
#endif
if (FatalError)
{
@ -2022,6 +2065,9 @@ CleanupProc(int pid,
bp = (Backend *) DLE_VAL(curr);
if (bp->pid == pid)
{
#ifdef EXEC_BACKEND
ShmemBackendArrayRemove(bp->pid);
#endif
DLRemove(curr);
free(bp);
DLFreeElem(curr);
@ -2092,6 +2138,9 @@ CleanupProc(int pid,
/*
* Found entry for freshly-dead backend, so remove it.
*/
#ifdef EXEC_BACKEND
ShmemBackendArrayRemove(bp->pid);
#endif
DLRemove(curr);
free(bp);
DLFreeElem(curr);
@ -2296,6 +2345,9 @@ BackendStartup(Port *port)
*/
bn->pid = pid;
bn->cancel_key = MyCancelKey;
#ifdef EXEC_BACKEND
ShmemBackendArrayAdd(bn);
#endif
DLAddHead(BackendList, DLNewElem(bn));
return STATUS_OK;
@ -2642,6 +2694,9 @@ SubPostmasterMain(int argc, char* argv[])
memset((void*)&port, 0, sizeof(Port));
Assert(argc == 2);
/* Do this sooner rather than later... */
IsUnderPostmaster = true; /* we are a postmaster subprocess now */
/* Setup global context */
MemoryContextInit();
InitializeGUCOptions();
@ -2661,6 +2716,9 @@ SubPostmasterMain(int argc, char* argv[])
load_user();
load_group();
/* Attach process to shared segments */
AttachSharedMemoryAndSemaphores();
/* Run backend */
proc_exit(BackendRun(&port));
}
@ -3129,6 +3187,9 @@ SSDataBase(int xlop)
bn->pid = pid;
bn->cancel_key = PostmasterRandom();
#ifdef EXEC_BACKEND
ShmemBackendArrayAdd(bn);
#endif
DLAddHead(BackendList, DLNewElem(bn));
/*
@ -3278,6 +3339,7 @@ write_backend_variables(Port *port)
write_var(ShmemIndexLock,fp);
write_var(ShmemVariableCache,fp);
write_var(ShmemIndexAlloc,fp);
write_var(ShmemBackendArray,fp);
write_var(LWLockArray,fp);
write_var(ProcStructLock,fp);
@ -3285,6 +3347,7 @@ write_backend_variables(Port *port)
write_var(PreAuthDelay,fp);
write_var(debug_flag,fp);
write_var(PostmasterPid,fp);
/* Release file */
if (FreeFile(fp))
@ -3338,6 +3401,7 @@ read_backend_variables(unsigned long id, Port *port)
read_var(ShmemIndexLock,fp);
read_var(ShmemVariableCache,fp);
read_var(ShmemIndexAlloc,fp);
read_var(ShmemBackendArray,fp);
read_var(LWLockArray,fp);
read_var(ProcStructLock,fp);
@ -3345,6 +3409,7 @@ read_backend_variables(unsigned long id, Port *port)
read_var(PreAuthDelay,fp);
read_var(debug_flag,fp);
read_var(PostmasterPid,fp);
/* Release file */
FreeFile(fp);
@ -3354,6 +3419,55 @@ read_backend_variables(unsigned long id, Port *port)
errmsg("could not remove file \"%s\": %m", filename)));
}
size_t ShmemBackendArraySize(void)
{
return (NUM_BACKENDARRAY_ELEMS*sizeof(Backend));
}
void ShmemBackendArrayAllocation(void)
{
size_t size = ShmemBackendArraySize();
ShmemBackendArray = (Backend*)ShmemAlloc(size);
memset(ShmemBackendArray, 0, size);
}
static void ShmemBackendArrayAdd(Backend *bn)
{
int i;
for (i = 0; i < NUM_BACKENDARRAY_ELEMS; i++)
{
/* Find an empty slot */
if (ShmemBackendArray[i].pid == 0)
{
ShmemBackendArray[i] = *bn;
return;
}
}
/* FIXME: [fork/exec] some sort of error */
abort();
}
static void ShmemBackendArrayRemove(pid_t pid)
{
int i;
for (i = 0; i < NUM_BACKENDARRAY_ELEMS; i++)
{
if (ShmemBackendArray[i].pid == pid)
{
/* Mark the slot as empty */
ShmemBackendArray[i].pid = 0;
return;
}
}
/* Something stronger than WARNING here? */
ereport(WARNING,
(errmsg_internal("unable to find backend entry with pid %d",
pid)));
}
#endif
#ifdef WIN32
@ -3393,14 +3507,111 @@ pid_t win32_forkexec(const char* path, char *argv[])
return -1;
}
/*
FIXME: [fork/exec] we might need to keep the following handle/s,
depending on how we implement signalling.
*/
CloseHandle(pi.hProcess);
if (!IsUnderPostmaster)
/* We are the Postmaster creating a child... */
win32_AddChild(pi.dwProcessId,pi.hProcess);
else
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return pi.dwProcessId;
}
/*
* Note: The following three functions must not be interrupted (eg. by signals).
* As the Postgres Win32 signalling architecture (currently) requires polling,
* or APC checking functions which aren't used here, this is not an issue.
*
* We keep two separate arrays, instead of a single array of pid/HANDLE structs,
* to avoid having to re-create a handle array for WaitForMultipleObjects on
* each call to win32_waitpid.
*/
static void win32_AddChild(pid_t pid, HANDLE handle)
{
Assert(win32_childPIDArray && win32_childHNDArray);
if (win32_numChildren < NUM_BACKENDARRAY_ELEMS)
{
win32_childPIDArray[win32_numChildren] = pid;
win32_childHNDArray[win32_numChildren] = handle;
++win32_numChildren;
}
else
/* FIXME: [fork/exec] some sort of error */
abort();
}
static void win32_RemoveChild(pid_t pid)
{
int i;
Assert(win32_childPIDArray && win32_childHNDArray);
for (i = 0; i < win32_numChildren; i++)
{
if (win32_childPIDArray[i] == pid)
{
CloseHandle(win32_childHNDArray[i]);
/* Swap last entry into the "removed" one */
--win32_numChildren;
win32_childPIDArray[win32_numChildren] = win32_childPIDArray[i];
win32_childHNDArray[win32_numChildren] = win32_childHNDArray[i];
return;
}
}
/* Something stronger than WARNING here? */
ereport(WARNING,
(errmsg_internal("unable to find child entry with pid %d",
pid)));
}
static pid_t win32_waitpid(int *exitstatus)
{
Assert(win32_childPIDArray && win32_childHNDArray);
elog(DEBUG3,"waiting on %d children",win32_numChildren);
if (win32_numChildren > 0)
{
/*
* Note: Do NOT use WaitForMultipleObjectsEx, as we don't
* want to run queued APCs here.
*/
int index;
DWORD exitCode;
DWORD ret = WaitForMultipleObjects(win32_numChildren,win32_childHNDArray,FALSE,0);
switch (ret)
{
case WAIT_FAILED:
ereport(ERROR,
(errmsg_internal("failed to wait on %d children",
win32_numChildren)));
/* Fall through to WAIT_TIMEOUTs return */
case WAIT_TIMEOUT:
/* No children have finished */
return -1;
default:
/* Get the exit code, and return the PID of, the respective process */
index = ret-WAIT_OBJECT_0;
Assert(index >= 0 && index < win32_numChildren);
if (!GetExitCodeProcess(win32_childHNDArray[index],&exitCode))
/*
* If we get this far, this should never happen, but, then again...
* No choice other than to assume a catastrophic failure.
*/
ereport(FATAL,
(errmsg_internal("failed to get exit code for child %d",
win32_childPIDArray[index])));
*exitstatus = (int)exitCode;
return win32_childPIDArray[index];
}
}
/* No children */
return -1;
}
#endif

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.62 2004/01/26 22:54:57 momjian Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.63 2004/01/26 22:59:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -63,6 +63,9 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
size += LWLockShmemSize();
size += SInvalShmemSize(maxBackends);
size += FreeSpaceShmemSize();
#ifdef EXEC_BACKEND
size += ShmemBackendArraySize();
#endif
#ifdef STABLE_MEMORY_STORAGE
size += MMShmemSize();
#endif
@ -132,6 +135,13 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
* Set up child-to-postmaster signaling mechanism
*/
PMSignalInit();
#ifdef EXEC_BACKEND
/*
* Alloc the win32 shared backend array
*/
ShmemBackendArrayAllocation();
#endif
}

View File

@ -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.10 2004/01/26 22:54:57 momjian Exp $
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.11 2004/01/26 22:59:53 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@ -63,8 +63,8 @@ SendPostmasterSignal(PMSignalReason reason)
return;
/* Atomically set the proper flag */
PMSignalFlags[reason] = true;
/* Send signal to postmaster (assume it is our direct parent) */
kill(getppid(), SIGUSR1);
/* Send signal to postmaster */
kill(PostmasterPid, SIGUSR1);
}
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.385 2004/01/26 22:54:57 momjian Exp $
* $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.386 2004/01/26 22:59:53 momjian Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
@ -2535,9 +2535,7 @@ PostgresMain(int argc, char *argv[], const char *username)
errmsg("invalid command-line arguments for server process"),
errhint("Try \"%s --help\" for more information.", argv[0])));
}
#ifdef EXEC_BACKEND
AttachSharedMemoryAndSemaphores();
#endif
XLOGPathInit();
BaseInit();

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.79 2004/01/26 22:54:57 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/init/globals.c,v 1.80 2004/01/26 22:59:53 momjian Exp $
*
* NOTES
* Globals used all over the place should be declared here and not
@ -53,6 +53,8 @@ BackendId MyBackendId;
char *DatabasePath = NULL;
Oid MyDatabaseId = InvalidOid;
pid_t PostmasterPid = 0;
/* these are initialized for the bootstrap/standalone case: */
bool IsPostmasterEnvironment = false;
bool IsUnderPostmaster = false;

View File

@ -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.147 2004/01/26 22:54:57 momjian Exp $
* $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.148 2004/01/26 22:59:53 momjian Exp $
*
* NOTES
* some of the information in this file should be moved to
@ -109,10 +109,14 @@ do { \
#else
#define PG_USLEEP(_usec) \
do { \
Sleep(_usec < 500) ? 1 : (_usec+500)/ 1000); \
Sleep((_usec) < 500 ? 1 : ((_usec)+500)/ 1000); \
} while(0)
#endif
#ifdef WIN32
#define ftruncate(a,b) chsize(a,b)
#endif
/*****************************************************************************
* globals.h -- *
*****************************************************************************/
@ -132,6 +136,7 @@ extern void ClosePostmasterPorts(bool pgstat_too);
/*
* from utils/init/globals.c
*/
extern pid_t PostmasterPid;
extern bool IsPostmasterEnvironment;
extern bool IsUnderPostmaster;

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.15 2004/01/26 22:54:58 momjian Exp $ */
/* $PostgreSQL: pgsql/src/include/port/win32.h,v 1.16 2004/01/26 22:59:54 momjian Exp $ */
/* undefine and redefine after #include */
#undef mkdir
@ -15,7 +15,7 @@
#define NOFILE 100
/* defines for dynamic linking on Win32 platform */
#ifdef __CYGWIN__
#if defined(__CYGWIN__) || defined(__MINGW32__)
#if __GNUC__ && ! defined (__declspec)
#error You need egcs 1.1 or newer for compiling!
@ -27,7 +27,7 @@
#define DLLIMPORT __declspec (dllimport)
#endif
#elif defined(WIN32) && defined(_MSC_VER) /* not CYGWIN */
#elif defined(WIN32) && defined(_MSC_VER) /* not CYGWIN or MingW */
#if defined(_DLL)
#define DLLIMPORT __declspec (dllexport)
@ -35,7 +35,7 @@
#define DLLIMPORT __declspec (dllimport)
#endif
#else /* not CYGWIN, not MSVC */
#else /* not CYGWIN, not MSVC, not MingW */
#define DLLIMPORT
#endif