]> granicus.if.org Git - postgresql/commitdiff
Ensure that 'errno' is saved and restored by all signal handlers that
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Dec 2000 17:33:42 +0000 (17:33 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Dec 2000 17:33:42 +0000 (17:33 +0000)
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.

src/backend/commands/async.c
src/backend/postmaster/postmaster.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/bin/psql/common.c
src/interfaces/libpq/fe-connect.c

index 6316262d042ff9e654763d07caf648a8bc2840fe..b86f2421eb8403fd9b0cb73d6c8f25f8536f6811 100644 (file)
@@ -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;
 }
 
 /*
index ca7f4fafa9c9277b91ee0255713b38dd40d4f5f6..c119f1301fe09c42848a2502dfe6e470efa67a38 100644 (file)
@@ -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;
 }
 
 /*
index a95432e0f8216c1f9ca5c2ffea65705bf0dbcb62..6b5159dbf04219c66e08633cc09051591da23b03 100644 (file)
@@ -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 $
  *
  *-------------------------------------------------------------------------
  */
  *             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
index 706b5d1fbf136606dbcc5d3de7aff436eb26dd6e..02c1459052d7b5f209fd2cbf688d419b27537ad4 100644 (file)
@@ -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");
        }
 
        /*
index cc57771b70e3a083737358299dc2f7f530949b19..ccbbb6c144312e2b665392bc1393a7a21b137617 100644 (file)
@@ -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 */
index c95ee99b94f147776342ff4540b29b6fa06a0ff6..868b73f6f7cb24640254e6287953de64af884368 100644 (file)
@@ -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;
 }