summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-12-18 17:33:42 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-12-18 17:33:42 +0000
commit5491233f5245c464be2286ad894448b21ef757db (patch)
tree8badaae022de82ec4cd53ffe42e2c22e681c394d
parentc431db9714bfca24f05fd301ae2f027f83689e4f (diff)
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.
-rw-r--r--src/backend/commands/async.c5
-rw-r--r--src/backend/postmaster/postmaster.c57
-rw-r--r--src/backend/storage/lmgr/proc.c14
-rw-r--r--src/backend/tcop/postgres.c7
-rw-r--r--src/bin/psql/common.c5
-rw-r--r--src/interfaces/libpq/fe-connect.c7
6 files changed, 79 insertions, 16 deletions
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 6316262d042..b86f2421eb8 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -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;
}
/*
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index ca7f4fafa9c..c119f1301fe 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -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;
}
/*
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index a95432e0f82..6b5159dbf04 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -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
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 706b5d1fbf1..02c1459052d 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -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");
}
/*
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index cc57771b70e..ccbbb6c1443 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -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 */
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index c95ee99b94f..868b73f6f7c 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -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;
}