Commit 5491233f authored by Tom Lane's avatar Tom Lane

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.
parent c431db97
......@@ -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");
}
/*
......
......@@ -3,7 +3,7 @@
*
* 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 "common.h"
......@@ -258,6 +258,8 @@ volatile bool cancel_pressed;
void
handle_sigint(SIGNAL_ARGS)
{
int save_errno = errno;
/* Don't muck around if copying in or prompting for a password. */
if ((copy_in_state && pset.cur_cmd_interactive) || prompt_state)
return;
......@@ -274,6 +276,7 @@ handle_sigint(SIGNAL_ARGS)
write_stderr("Could not send cancel request: ");
write_stderr(PQerrorMessage(cancelConn));
}
errno = save_errno; /* just in case the write changed it */
}
#endif /* not WIN32 */
......
......@@ -8,7 +8,7 @@
*
*
* 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
* just as dangerous. We avoid sprintf here for that reason. Building up
* 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
* INITIAL_EXPBUFFER_SIZE (currently 256), since we dare not try to
......@@ -2093,6 +2094,7 @@ PQresetPoll(PGconn *conn)
int
PQrequestCancel(PGconn *conn)
{
int save_errno = errno;
int tmpsock = -1;
struct
{
......@@ -2109,6 +2111,7 @@ PQrequestCancel(PGconn *conn)
strcpy(conn->errorMessage.data,
"PQrequestCancel() -- connection is not open\n");
conn->errorMessage.len = strlen(conn->errorMessage.data);
errno = save_errno;
return FALSE;
}
......@@ -2154,6 +2157,7 @@ PQrequestCancel(PGconn *conn)
close(tmpsock);
#endif
errno = save_errno;
return TRUE;
cancel_errReturn:
......@@ -2168,6 +2172,7 @@ cancel_errReturn:
close(tmpsock);
#endif
}
errno = save_errno;
return FALSE;
}
......
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