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:
Tom Lane 2000-12-18 17:33:42 +00:00
parent c431db9714
commit 5491233f52
6 changed files with 79 additions and 16 deletions

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 void
Async_NotifyHandler(SIGNAL_ARGS) Async_NotifyHandler(SIGNAL_ARGS)
{ {
int save_errno = errno;
/* /*
* Note: this is a SIGNAL HANDLER. You must be very wary what you do * Note: this is a SIGNAL HANDLER. You must be very wary what you do
@ -637,6 +638,8 @@ Async_NotifyHandler(SIGNAL_ARGS)
*/ */
notifyInterruptOccurred = 1; notifyInterruptOccurred = 1;
} }
errno = save_errno;
} }
/* /*

View File

@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* *
@ -217,7 +217,7 @@ static int initMasks(fd_set *rmask, fd_set *wmask);
static char *canAcceptConnections(void); static char *canAcceptConnections(void);
static long PostmasterRandom(void); static long PostmasterRandom(void);
static void RandomSalt(char *salt); static void RandomSalt(char *salt);
static void SignalChildren(SIGNAL_ARGS); static void SignalChildren(int signal);
static int CountChildren(void); static int CountChildren(void);
static bool CreateOptsFile(int argc, char *argv[]); static bool CreateOptsFile(int argc, char *argv[]);
@ -1303,10 +1303,13 @@ reset_shared(unsigned short port)
static void static void
SIGHUP_handler(SIGNAL_ARGS) SIGHUP_handler(SIGNAL_ARGS)
{ {
int save_errno = errno;
if (Shutdown > SmartShutdown) if (Shutdown > SmartShutdown)
return; return;
got_SIGHUP = true; got_SIGHUP = true;
SignalChildren(SIGHUP); SignalChildren(SIGHUP);
errno = save_errno;
} }
@ -1317,6 +1320,8 @@ SIGHUP_handler(SIGNAL_ARGS)
static void static void
pmdie(SIGNAL_ARGS) pmdie(SIGNAL_ARGS)
{ {
int save_errno = errno;
PG_SETMASK(&BlockSig); PG_SETMASK(&BlockSig);
if (DebugLvl >= 1) if (DebugLvl >= 1)
@ -1330,8 +1335,12 @@ pmdie(SIGNAL_ARGS)
* Send SIGUSR2 to all children (AsyncNotifyHandler) * Send SIGUSR2 to all children (AsyncNotifyHandler)
*/ */
if (Shutdown > SmartShutdown) if (Shutdown > SmartShutdown)
{
errno = save_errno;
return; return;
}
SignalChildren(SIGUSR2); SignalChildren(SIGUSR2);
errno = save_errno;
return; return;
case SIGTERM: case SIGTERM:
@ -1342,24 +1351,34 @@ pmdie(SIGNAL_ARGS)
* let children to end their work and ShutdownDataBase. * let children to end their work and ShutdownDataBase.
*/ */
if (Shutdown >= SmartShutdown) if (Shutdown >= SmartShutdown)
{
errno = save_errno;
return; return;
}
Shutdown = SmartShutdown; Shutdown = SmartShutdown;
tnow = time(NULL); tnow = time(NULL);
fprintf(stderr, "Smart Shutdown request at %s", ctime(&tnow)); fprintf(stderr, "Smart Shutdown request at %s", ctime(&tnow));
fflush(stderr); fflush(stderr);
if (DLGetHead(BackendList)) /* let reaper() handle this */ if (DLGetHead(BackendList)) /* let reaper() handle this */
{
errno = save_errno;
return; return;
}
/* /*
* No children left. Shutdown data base system. * No children left. Shutdown data base system.
*/ */
if (StartupPID > 0 || FatalError) /* let reaper() handle if (StartupPID > 0 || FatalError) /* let reaper() handle
* this */ * this */
{
errno = save_errno;
return; return;
}
if (ShutdownPID > 0) if (ShutdownPID > 0)
abort(); abort();
ShutdownPID = ShutdownDataBase(); ShutdownPID = ShutdownDataBase();
errno = save_errno;
return; return;
case SIGINT: case SIGINT:
@ -1371,7 +1390,10 @@ pmdie(SIGNAL_ARGS)
* and exit) and ShutdownDataBase. * and exit) and ShutdownDataBase.
*/ */
if (Shutdown >= FastShutdown) if (Shutdown >= FastShutdown)
{
errno = save_errno;
return; return;
}
tnow = time(NULL); tnow = time(NULL);
fprintf(stderr, "Fast Shutdown request at %s", ctime(&tnow)); fprintf(stderr, "Fast Shutdown request at %s", ctime(&tnow));
fflush(stderr); fflush(stderr);
@ -1384,11 +1406,13 @@ pmdie(SIGNAL_ARGS)
fflush(stderr); fflush(stderr);
SignalChildren(SIGTERM); SignalChildren(SIGTERM);
} }
errno = save_errno;
return; return;
} }
if (Shutdown > NoShutdown) if (Shutdown > NoShutdown)
{ {
Shutdown = FastShutdown; Shutdown = FastShutdown;
errno = save_errno;
return; return;
} }
Shutdown = FastShutdown; Shutdown = FastShutdown;
@ -1398,11 +1422,15 @@ pmdie(SIGNAL_ARGS)
*/ */
if (StartupPID > 0 || FatalError) /* let reaper() handle if (StartupPID > 0 || FatalError) /* let reaper() handle
* this */ * this */
{
errno = save_errno;
return; return;
}
if (ShutdownPID > 0) if (ShutdownPID > 0)
abort(); abort();
ShutdownPID = ShutdownDataBase(); ShutdownPID = ShutdownDataBase();
errno = save_errno;
return; return;
case SIGQUIT: case SIGQUIT:
@ -1435,18 +1463,18 @@ pmdie(SIGNAL_ARGS)
static void static void
reaper(SIGNAL_ARGS) reaper(SIGNAL_ARGS)
{ {
/* GH: replace waitpid for !HAVE_WAITPID. Does this work ? */ int save_errno = errno;
#ifdef HAVE_WAITPID #ifdef HAVE_WAITPID
int status; /* backend exit status */ int status; /* backend exit status */
#else #else
union wait status; /* backend exit status */ union wait status; /* backend exit status */
#endif #endif
int exitstatus; int exitstatus;
int pid; /* process id of dead backend */ int pid; /* process id of dead backend */
PG_SETMASK(&BlockSig); PG_SETMASK(&BlockSig);
/* It's not really necessary to reset the handler each time is it? */
pqsignal(SIGCHLD, reaper);
if (DebugLvl) if (DebugLvl)
fprintf(stderr, "%s: reaping dead processes...\n", fprintf(stderr, "%s: reaping dead processes...\n",
@ -1499,12 +1527,11 @@ reaper(SIGNAL_ARGS)
CheckPointPID = 0; CheckPointPID = 0;
checkpointed = time(NULL); checkpointed = time(NULL);
pqsignal(SIGCHLD, reaper); errno = save_errno;
return; return;
} }
CleanupProc(pid, exitstatus); CleanupProc(pid, exitstatus);
} }
pqsignal(SIGCHLD, reaper);
if (FatalError) if (FatalError)
{ {
@ -1513,9 +1540,15 @@ reaper(SIGNAL_ARGS)
* Wait for all children exit, then reset shmem and StartupDataBase. * Wait for all children exit, then reset shmem and StartupDataBase.
*/ */
if (DLGetHead(BackendList)) if (DLGetHead(BackendList))
{
errno = save_errno;
return; return;
}
if (StartupPID > 0 || ShutdownPID > 0) if (StartupPID > 0 || ShutdownPID > 0)
{
errno = save_errno;
return; return;
}
tnow = time(NULL); tnow = time(NULL);
fprintf(stderr, "Server processes were terminated at %s" fprintf(stderr, "Server processes were terminated at %s"
"Reinitializing shared memory and semaphores\n", "Reinitializing shared memory and semaphores\n",
@ -1526,18 +1559,26 @@ reaper(SIGNAL_ARGS)
reset_shared(PostPortNumber); reset_shared(PostPortNumber);
StartupPID = StartupDataBase(); StartupPID = StartupDataBase();
errno = save_errno;
return; return;
} }
if (Shutdown > NoShutdown) if (Shutdown > NoShutdown)
{ {
if (DLGetHead(BackendList)) if (DLGetHead(BackendList))
{
errno = save_errno;
return; return;
}
if (StartupPID > 0 || ShutdownPID > 0) if (StartupPID > 0 || ShutdownPID > 0)
{
errno = save_errno;
return; return;
}
ShutdownPID = ShutdownDataBase(); ShutdownPID = ShutdownDataBase();
} }
errno = save_errno;
} }
/* /*
@ -2002,6 +2043,7 @@ ExitPostmaster(int status)
static void static void
dumpstatus(SIGNAL_ARGS) dumpstatus(SIGNAL_ARGS)
{ {
int save_errno = errno;
Dlelem *curr; Dlelem *curr;
PG_SETMASK(&BlockSig); PG_SETMASK(&BlockSig);
@ -2015,6 +2057,7 @@ dumpstatus(SIGNAL_ARGS)
fprintf(stderr, "\tsock %d\n", port->sock); fprintf(stderr, "\tsock %d\n", port->sock);
curr = DLGetSucc(curr); curr = DLGetSucc(curr);
} }
errno = save_errno;
} }
/* /*

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * This is so that we can support more backends. (system-wide semaphore
* sets run out pretty fast.) -ay 4/95 * 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 "postgres.h"
#include <errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
#include <signal.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 static bool
@ -623,10 +624,11 @@ ins:;
waitQueue->size++; waitQueue->size++;
lock->waitMask |= myMask; lock->waitMask |= myMask;
SpinRelease(spinlock);
MyProc->errType = NO_ERROR; /* initialize result for success */ MyProc->errType = NO_ERROR; /* initialize result for success */
SpinRelease(spinlock);
/* -------------- /* --------------
* Set timer so we can wake up after awhile and check for a deadlock. * 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 * If a deadlock is detected, the handler releases the process's
@ -826,6 +828,7 @@ ProcAddLock(SHM_QUEUE *elem)
void void
HandleDeadLock(SIGNAL_ARGS) HandleDeadLock(SIGNAL_ARGS)
{ {
int save_errno = errno;
LOCK *mywaitlock; LOCK *mywaitlock;
LockLockTable(); LockLockTable();
@ -846,6 +849,7 @@ HandleDeadLock(SIGNAL_ARGS)
MyProc->links.next == INVALID_OFFSET) MyProc->links.next == INVALID_OFFSET)
{ {
UnlockLockTable(); UnlockLockTable();
errno = save_errno;
return; return;
} }
@ -858,6 +862,7 @@ HandleDeadLock(SIGNAL_ARGS)
{ {
/* No deadlock, so keep waiting */ /* No deadlock, so keep waiting */
UnlockLockTable(); UnlockLockTable();
errno = save_errno;
return; return;
} }
@ -891,6 +896,7 @@ HandleDeadLock(SIGNAL_ARGS)
* conditions. i don't claim to understand this... * conditions. i don't claim to understand this...
*/ */
UnlockLockTable(); UnlockLockTable();
errno = save_errno;
} }
void void

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* this is the "main" module of the postgres backend and * this is the "main" module of the postgres backend and
@ -984,8 +984,11 @@ FloatExceptionHandler(SIGNAL_ARGS)
static void static void
QueryCancelHandler(SIGNAL_ARGS) QueryCancelHandler(SIGNAL_ARGS)
{ {
int save_errno = errno;
QueryCancel = true; QueryCancel = true;
LockWaitCancel(); LockWaitCancel();
errno = save_errno;
} }
void void
@ -1646,7 +1649,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha
if (!IsUnderPostmaster) if (!IsUnderPostmaster)
{ {
puts("\nPOSTGRES backend interactive interface "); 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");
} }
/* /*

View File

@ -3,7 +3,7 @@
* *
* Copyright 2000 by PostgreSQL Global Development Group * Copyright 2000 by PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.28 2000/12/15 17:54:43 petere Exp $ * $Header: /cvsroot/pgsql/src/bin/psql/common.c,v 1.29 2000/12/18 17:33:42 tgl Exp $
*/ */
#include "postgres.h" #include "postgres.h"
#include "common.h" #include "common.h"
@ -258,6 +258,8 @@ volatile bool cancel_pressed;
void void
handle_sigint(SIGNAL_ARGS) handle_sigint(SIGNAL_ARGS)
{ {
int save_errno = errno;
/* Don't muck around if copying in or prompting for a password. */ /* Don't muck around if copying in or prompting for a password. */
if ((copy_in_state && pset.cur_cmd_interactive) || prompt_state) if ((copy_in_state && pset.cur_cmd_interactive) || prompt_state)
return; return;
@ -274,6 +276,7 @@ handle_sigint(SIGNAL_ARGS)
write_stderr("Could not send cancel request: "); write_stderr("Could not send cancel request: ");
write_stderr(PQerrorMessage(cancelConn)); write_stderr(PQerrorMessage(cancelConn));
} }
errno = save_errno; /* just in case the write changed it */
} }
#endif /* not WIN32 */ #endif /* not WIN32 */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.154 2000/12/07 02:04:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.155 2000/12/18 17:33:41 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -2084,6 +2084,7 @@ PQresetPoll(PGconn *conn)
* malloc/free are often non-reentrant, and anything that might call them is * malloc/free are often non-reentrant, and anything that might call them is
* just as dangerous. We avoid sprintf here for that reason. Building up * just as dangerous. We avoid sprintf here for that reason. Building up
* error messages with strcpy/strcat is tedious but should be quite safe. * error messages with strcpy/strcat is tedious but should be quite safe.
* We also save/restore errno in case the signal handler support doesn't.
* *
* NOTE: this routine must not generate any error message longer than * NOTE: this routine must not generate any error message longer than
* INITIAL_EXPBUFFER_SIZE (currently 256), since we dare not try to * INITIAL_EXPBUFFER_SIZE (currently 256), since we dare not try to
@ -2093,6 +2094,7 @@ PQresetPoll(PGconn *conn)
int int
PQrequestCancel(PGconn *conn) PQrequestCancel(PGconn *conn)
{ {
int save_errno = errno;
int tmpsock = -1; int tmpsock = -1;
struct struct
{ {
@ -2109,6 +2111,7 @@ PQrequestCancel(PGconn *conn)
strcpy(conn->errorMessage.data, strcpy(conn->errorMessage.data,
"PQrequestCancel() -- connection is not open\n"); "PQrequestCancel() -- connection is not open\n");
conn->errorMessage.len = strlen(conn->errorMessage.data); conn->errorMessage.len = strlen(conn->errorMessage.data);
errno = save_errno;
return FALSE; return FALSE;
} }
@ -2154,6 +2157,7 @@ PQrequestCancel(PGconn *conn)
close(tmpsock); close(tmpsock);
#endif #endif
errno = save_errno;
return TRUE; return TRUE;
cancel_errReturn: cancel_errReturn:
@ -2168,6 +2172,7 @@ cancel_errReturn:
close(tmpsock); close(tmpsock);
#endif #endif
} }
errno = save_errno;
return FALSE; return FALSE;
} }