mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Ensure that 'errno' is saved and restored by all signal handlers that
might change it. Experimentation shows that the signal handler call mechanism does not save/restore errno for you, at least not on Linux or HPUX, so this is definitely a real risk.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.73 2000/11/28 23:27:54 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.74 2000/12/18 17:33:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -589,6 +589,7 @@ AtAbort_Notify()
|
||||
void
|
||||
Async_NotifyHandler(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
/*
|
||||
* Note: this is a SIGNAL HANDLER. You must be very wary what you do
|
||||
@@ -637,6 +638,8 @@ Async_NotifyHandler(SIGNAL_ARGS)
|
||||
*/
|
||||
notifyInterruptOccurred = 1;
|
||||
}
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.198 2000/12/03 20:45:34 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.199 2000/12/18 17:33:40 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@@ -217,7 +217,7 @@ static int initMasks(fd_set *rmask, fd_set *wmask);
|
||||
static char *canAcceptConnections(void);
|
||||
static long PostmasterRandom(void);
|
||||
static void RandomSalt(char *salt);
|
||||
static void SignalChildren(SIGNAL_ARGS);
|
||||
static void SignalChildren(int signal);
|
||||
static int CountChildren(void);
|
||||
static bool CreateOptsFile(int argc, char *argv[]);
|
||||
|
||||
@@ -1303,10 +1303,13 @@ reset_shared(unsigned short port)
|
||||
static void
|
||||
SIGHUP_handler(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
if (Shutdown > SmartShutdown)
|
||||
return;
|
||||
got_SIGHUP = true;
|
||||
SignalChildren(SIGHUP);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
|
||||
@@ -1317,6 +1320,8 @@ SIGHUP_handler(SIGNAL_ARGS)
|
||||
static void
|
||||
pmdie(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
PG_SETMASK(&BlockSig);
|
||||
|
||||
if (DebugLvl >= 1)
|
||||
@@ -1330,8 +1335,12 @@ pmdie(SIGNAL_ARGS)
|
||||
* Send SIGUSR2 to all children (AsyncNotifyHandler)
|
||||
*/
|
||||
if (Shutdown > SmartShutdown)
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
SignalChildren(SIGUSR2);
|
||||
errno = save_errno;
|
||||
return;
|
||||
|
||||
case SIGTERM:
|
||||
@@ -1342,24 +1351,34 @@ pmdie(SIGNAL_ARGS)
|
||||
* let children to end their work and ShutdownDataBase.
|
||||
*/
|
||||
if (Shutdown >= SmartShutdown)
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
Shutdown = SmartShutdown;
|
||||
tnow = time(NULL);
|
||||
fprintf(stderr, "Smart Shutdown request at %s", ctime(&tnow));
|
||||
fflush(stderr);
|
||||
if (DLGetHead(BackendList)) /* let reaper() handle this */
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* No children left. Shutdown data base system.
|
||||
*/
|
||||
if (StartupPID > 0 || FatalError) /* let reaper() handle
|
||||
* this */
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
if (ShutdownPID > 0)
|
||||
abort();
|
||||
|
||||
ShutdownPID = ShutdownDataBase();
|
||||
errno = save_errno;
|
||||
return;
|
||||
|
||||
case SIGINT:
|
||||
@@ -1371,7 +1390,10 @@ pmdie(SIGNAL_ARGS)
|
||||
* and exit) and ShutdownDataBase.
|
||||
*/
|
||||
if (Shutdown >= FastShutdown)
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
tnow = time(NULL);
|
||||
fprintf(stderr, "Fast Shutdown request at %s", ctime(&tnow));
|
||||
fflush(stderr);
|
||||
@@ -1384,11 +1406,13 @@ pmdie(SIGNAL_ARGS)
|
||||
fflush(stderr);
|
||||
SignalChildren(SIGTERM);
|
||||
}
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
if (Shutdown > NoShutdown)
|
||||
{
|
||||
Shutdown = FastShutdown;
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
Shutdown = FastShutdown;
|
||||
@@ -1398,11 +1422,15 @@ pmdie(SIGNAL_ARGS)
|
||||
*/
|
||||
if (StartupPID > 0 || FatalError) /* let reaper() handle
|
||||
* this */
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
if (ShutdownPID > 0)
|
||||
abort();
|
||||
|
||||
ShutdownPID = ShutdownDataBase();
|
||||
errno = save_errno;
|
||||
return;
|
||||
|
||||
case SIGQUIT:
|
||||
@@ -1435,18 +1463,18 @@ pmdie(SIGNAL_ARGS)
|
||||
static void
|
||||
reaper(SIGNAL_ARGS)
|
||||
{
|
||||
/* GH: replace waitpid for !HAVE_WAITPID. Does this work ? */
|
||||
int save_errno = errno;
|
||||
#ifdef HAVE_WAITPID
|
||||
int status; /* backend exit status */
|
||||
|
||||
#else
|
||||
union wait status; /* backend exit status */
|
||||
|
||||
#endif
|
||||
int exitstatus;
|
||||
int pid; /* process id of dead backend */
|
||||
|
||||
PG_SETMASK(&BlockSig);
|
||||
/* It's not really necessary to reset the handler each time is it? */
|
||||
pqsignal(SIGCHLD, reaper);
|
||||
|
||||
if (DebugLvl)
|
||||
fprintf(stderr, "%s: reaping dead processes...\n",
|
||||
@@ -1499,12 +1527,11 @@ reaper(SIGNAL_ARGS)
|
||||
CheckPointPID = 0;
|
||||
checkpointed = time(NULL);
|
||||
|
||||
pqsignal(SIGCHLD, reaper);
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
CleanupProc(pid, exitstatus);
|
||||
}
|
||||
pqsignal(SIGCHLD, reaper);
|
||||
|
||||
if (FatalError)
|
||||
{
|
||||
@@ -1513,9 +1540,15 @@ reaper(SIGNAL_ARGS)
|
||||
* Wait for all children exit, then reset shmem and StartupDataBase.
|
||||
*/
|
||||
if (DLGetHead(BackendList))
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
if (StartupPID > 0 || ShutdownPID > 0)
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
tnow = time(NULL);
|
||||
fprintf(stderr, "Server processes were terminated at %s"
|
||||
"Reinitializing shared memory and semaphores\n",
|
||||
@@ -1526,18 +1559,26 @@ reaper(SIGNAL_ARGS)
|
||||
reset_shared(PostPortNumber);
|
||||
|
||||
StartupPID = StartupDataBase();
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Shutdown > NoShutdown)
|
||||
{
|
||||
if (DLGetHead(BackendList))
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
if (StartupPID > 0 || ShutdownPID > 0)
|
||||
{
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
ShutdownPID = ShutdownDataBase();
|
||||
}
|
||||
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2002,6 +2043,7 @@ ExitPostmaster(int status)
|
||||
static void
|
||||
dumpstatus(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
Dlelem *curr;
|
||||
|
||||
PG_SETMASK(&BlockSig);
|
||||
@@ -2015,6 +2057,7 @@ dumpstatus(SIGNAL_ARGS)
|
||||
fprintf(stderr, "\tsock %d\n", port->sock);
|
||||
curr = DLGetSucc(curr);
|
||||
}
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.87 2000/12/18 00:44:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.88 2000/12/18 17:33:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -48,10 +48,11 @@
|
||||
* This is so that we can support more backends. (system-wide semaphore
|
||||
* sets run out pretty fast.) -ay 4/95
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.87 2000/12/18 00:44:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.88 2000/12/18 17:33:41 tgl Exp $
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
@@ -298,7 +299,7 @@ InitProcess(void)
|
||||
}
|
||||
|
||||
/* -----------------------
|
||||
* get off the wait queue
|
||||
* get process off any wait queue it might be on
|
||||
* -----------------------
|
||||
*/
|
||||
static bool
|
||||
@@ -623,10 +624,11 @@ ins:;
|
||||
waitQueue->size++;
|
||||
|
||||
lock->waitMask |= myMask;
|
||||
SpinRelease(spinlock);
|
||||
|
||||
MyProc->errType = NO_ERROR; /* initialize result for success */
|
||||
|
||||
SpinRelease(spinlock);
|
||||
|
||||
/* --------------
|
||||
* Set timer so we can wake up after awhile and check for a deadlock.
|
||||
* If a deadlock is detected, the handler releases the process's
|
||||
@@ -826,6 +828,7 @@ ProcAddLock(SHM_QUEUE *elem)
|
||||
void
|
||||
HandleDeadLock(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
LOCK *mywaitlock;
|
||||
|
||||
LockLockTable();
|
||||
@@ -846,6 +849,7 @@ HandleDeadLock(SIGNAL_ARGS)
|
||||
MyProc->links.next == INVALID_OFFSET)
|
||||
{
|
||||
UnlockLockTable();
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -858,6 +862,7 @@ HandleDeadLock(SIGNAL_ARGS)
|
||||
{
|
||||
/* No deadlock, so keep waiting */
|
||||
UnlockLockTable();
|
||||
errno = save_errno;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -891,6 +896,7 @@ HandleDeadLock(SIGNAL_ARGS)
|
||||
* conditions. i don't claim to understand this...
|
||||
*/
|
||||
UnlockLockTable();
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.195 2000/12/18 00:44:47 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.196 2000/12/18 17:33:41 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@@ -984,8 +984,11 @@ FloatExceptionHandler(SIGNAL_ARGS)
|
||||
static void
|
||||
QueryCancelHandler(SIGNAL_ARGS)
|
||||
{
|
||||
int save_errno = errno;
|
||||
|
||||
QueryCancel = true;
|
||||
LockWaitCancel();
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1646,7 +1649,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface ");
|
||||
puts("$Revision: 1.195 $ $Date: 2000/12/18 00:44:47 $\n");
|
||||
puts("$Revision: 1.196 $ $Date: 2000/12/18 17:33:41 $\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user