]> granicus.if.org Git - postgresql/commitdiff
Merge three existing ways of signaling postmaster from child processes,
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 4 Nov 2001 19:55:31 +0000 (19:55 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 4 Nov 2001 19:55:31 +0000 (19:55 +0000)
so that only one signal number is used not three.  Flags in shared
memory tell the reason(s) for the current signal.  This method is
extensible to handle more signal reasons without chewing up even more
signal numbers, but the immediate reason is to keep pg_pwd reloads
separate from SIGHUP processing in the postmaster.
Also clean up some problems in the postmaster with delayed response to
checkpoint status changes --- basically, it wouldn't schedule a checkpoint
if it wasn't getting connection requests on a regular basis.

src/backend/access/transam/xlog.c
src/backend/commands/user.c
src/backend/postmaster/postmaster.c
src/backend/storage/ipc/Makefile
src/backend/storage/ipc/ipci.c
src/backend/storage/ipc/pmsignal.c [new file with mode: 0644]
src/backend/storage/ipc/sinvaladt.c
src/include/storage/pmsignal.h [new file with mode: 0644]

index c0bfe968d259677af3e00cfd8e62518c52f2aea4..e5c2f7d7582a83d9f0cd3eb6f68dd033ace7aad7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.80 2001/10/28 06:25:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.81 2001/11/04 19:55:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,7 @@
 #include "catalog/pg_control.h"
 #include "storage/bufpage.h"
 #include "storage/lwlock.h"
+#include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/sinval.h"
 #include "storage/spin.h"
@@ -1048,7 +1049,7 @@ XLogWrite(XLogwrtRqst WriteRqst)
                                {
                                        if (XLOG_DEBUG)
                                                elog(DEBUG, "XLogWrite: time for a checkpoint, signaling postmaster");
-                                       kill(getppid(), SIGUSR1);
+                                       SendPostmasterSignal(PMSIGNAL_DO_CHECKPOINT);
                                }
                        }
                        LWLockRelease(ControlFileLock);
index 3897a5c75ec7e582a7bda3fdbffe592fd3efef34..9b95ecad274aec0897b0da1afcde2c855ee59a6d 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.88 2001/11/02 18:39:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.89 2001/11/04 19:55:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -15,7 +15,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include <signal.h>
 #include <unistd.h>
 
 #include "access/heapam.h"
@@ -27,6 +26,7 @@
 #include "commands/user.h"
 #include "libpq/crypt.h"
 #include "miscadmin.h"
+#include "storage/pmsignal.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -180,8 +180,7 @@ write_password_file(Relation rel)
        /*
         * Signal the postmaster to reload its password-file cache.
         */
-       if (IsUnderPostmaster)
-               kill(getppid(), SIGHUP);
+       SendPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE);
 }
 
 
index 2c96486cd06e3c032e69a85741b9338c96d12d47..ae8e5a6fe159d8497e2454af199b4feb5cd83358 100644 (file)
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.254 2001/11/02 18:39:57 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.255 2001/11/04 19:55:31 tgl Exp $
  *
  * NOTES
  *
@@ -98,6 +98,7 @@
 #include "nodes/nodes.h"
 #include "storage/fd.h"
 #include "storage/ipc.h"
+#include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "access/xlog.h"
 #include "tcop/tcopprot.h"
@@ -155,9 +156,6 @@ int                 MaxBackends = DEF_MAXBACKENDS;
 
 static char *progname = (char *) NULL;
 
-/* flag to indicate that SIGHUP arrived during server loop */
-static volatile bool got_SIGHUP = false;
-
 /*
  * Default Values
  */
@@ -239,7 +237,8 @@ static void reset_shared(unsigned short port);
 static void SIGHUP_handler(SIGNAL_ARGS);
 static void pmdie(SIGNAL_ARGS);
 static void reaper(SIGNAL_ARGS);
-static void schedule_checkpoint(SIGNAL_ARGS);
+static void sigusr1_handler(SIGNAL_ARGS);
+static void dummy_handler(SIGNAL_ARGS);
 static void CleanupProc(int pid, int exitstatus);
 static int     DoBackend(Port *port);
 static void ExitPostmaster(int status);
@@ -722,9 +721,8 @@ PostmasterMain(int argc, char *argv[])
        pqsignal(SIGTERM, pmdie);       /* wait for children and ShutdownDataBase */
        pqsignal(SIGALRM, SIG_IGN); /* ignored */
        pqsignal(SIGPIPE, SIG_IGN); /* ignored */
-       pqsignal(SIGUSR1, schedule_checkpoint);         /* start a background
-                                                                                                * checkpoint */
-       pqsignal(SIGUSR2, pmdie);       /* send SIGUSR2, don't die */
+       pqsignal(SIGUSR1, sigusr1_handler);             /* message from child process */
+       pqsignal(SIGUSR2, dummy_handler);       /* unused, reserve for children */
        pqsignal(SIGCHLD, reaper);      /* handle child termination */
        pqsignal(SIGTTIN, SIG_IGN); /* ignored */
        pqsignal(SIGTTOU, SIG_IGN); /* ignored */
@@ -867,8 +865,19 @@ ServerLoop(void)
                Port       *port;
                fd_set          rmask,
                                        wmask;
-               struct timeval *timeout = NULL;
-               struct timeval timeout_tv;
+               struct timeval timeout;
+
+               /*
+                * The timeout for the select() below is normally set on the basis
+                * of the time to the next checkpoint.  However, if for some reason
+                * we don't have a next-checkpoint time, time out after 60 seconds.
+                * This keeps checkpoint scheduling from locking up when we get new
+                * connection requests infrequently (since we are likely to detect
+                * checkpoint completion just after enabling signals below, after
+                * we've already made the decision about how long to wait this time).
+                */
+               timeout.tv_sec = 60;
+               timeout.tv_usec = 0;
 
                if (CheckPointPID == 0 && checkpointed &&
                        Shutdown == NoShutdown && !FatalError && random_seed != 0)
@@ -878,12 +887,9 @@ ServerLoop(void)
                        if (CheckPointTimeout + checkpointed > now)
                        {
                                /*
-                                * Not time for checkpoint yet, so set a timeout for
-                                * select
+                                * Not time for checkpoint yet, so set select timeout
                                 */
-                               timeout_tv.tv_sec = CheckPointTimeout + checkpointed - now;
-                               timeout_tv.tv_usec = 0;
-                               timeout = &timeout_tv;
+                               timeout.tv_sec = CheckPointTimeout + checkpointed - now;
                        }
                        else
                        {
@@ -895,7 +901,10 @@ ServerLoop(void)
                                 * delay
                                 */
                                if (CheckPointPID == 0)
-                                       checkpointed = now - (9 * CheckPointTimeout) / 10;
+                               {
+                                       timeout.tv_sec = CheckPointTimeout / 10;
+                                       checkpointed = now + timeout.tv_sec - CheckPointTimeout;
+                               }
                        }
                }
 
@@ -907,31 +916,21 @@ ServerLoop(void)
 
                PG_SETMASK(&UnBlockSig);
 
-               if (select(nSockets, &rmask, &wmask, (fd_set *) NULL, timeout) < 0)
+               if (select(nSockets, &rmask, &wmask, (fd_set *) NULL, &timeout) < 0)
                {
                        PG_SETMASK(&BlockSig);
                        if (errno == EINTR || errno == EWOULDBLOCK)
                                continue;
-                       elog(DEBUG, "ServerLoop: select failed: %s", strerror(errno));
+                       elog(DEBUG, "ServerLoop: select failed: %m");
                        return STATUS_ERROR;
                }
 
                /*
-                * Block all signals until we wait again
+                * Block all signals until we wait again.  (This makes it safe
+                * for our signal handlers to do nontrivial work.)
                 */
                PG_SETMASK(&BlockSig);
 
-               /*
-                * Respond to signals, if needed
-                */
-               if (got_SIGHUP)
-               {
-                       got_SIGHUP = false;
-                       ProcessConfigFile(PGC_SIGHUP);
-                       load_hba_and_ident();
-                       load_password_cache();
-               }
-
                /*
                 * Select a random seed at the time of first receiving a request.
                 */
@@ -1382,10 +1381,13 @@ SIGHUP_handler(SIGNAL_ARGS)
 
        if (Shutdown <= SmartShutdown)
        {
-               got_SIGHUP = true;
                SignalChildren(SIGHUP);
+               ProcessConfigFile(PGC_SIGHUP);
+               load_hba_and_ident();
        }
 
+       PG_SETMASK(&UnBlockSig);
+
        errno = save_errno;
 }
 
@@ -1406,20 +1408,6 @@ pmdie(SIGNAL_ARGS)
 
        switch (postgres_signal_arg)
        {
-               case SIGUSR2:
-
-                       /*
-                        * Send SIGUSR2 to all children (AsyncNotifyHandler)
-                        */
-                       if (Shutdown > SmartShutdown)
-                       {
-                               errno = save_errno;
-                               return;
-                       }
-                       SignalChildren(SIGUSR2);
-                       errno = save_errno;
-                       return;
-
                case SIGTERM:
 
                        /*
@@ -1428,27 +1416,18 @@ pmdie(SIGNAL_ARGS)
                         * Wait for children to end their work and ShutdownDataBase.
                         */
                        if (Shutdown >= SmartShutdown)
-                       {
-                               errno = save_errno;
-                               return;
-                       }
+                               break;
                        Shutdown = SmartShutdown;
                        elog(DEBUG, "smart shutdown request");
                        if (DLGetHead(BackendList)) /* let reaper() handle this */
-                       {
-                               errno = save_errno;
-                               return;
-                       }
+                               break;
 
                        /*
                         * No children left. Shutdown data base system.
                         */
                        if (StartupPID > 0 || FatalError)       /* let reaper() handle
                                                                                                 * this */
-                       {
-                               errno = save_errno;
-                               return;
-                       }
+                               break;
                        if (ShutdownPID > 0)
                        {
                                elog(REALLYFATAL, "shutdown process %d already running",
@@ -1457,8 +1436,7 @@ pmdie(SIGNAL_ARGS)
                        }
 
                        ShutdownPID = ShutdownDataBase();
-                       errno = save_errno;
-                       return;
+                       break;
 
                case SIGINT:
 
@@ -1469,10 +1447,7 @@ pmdie(SIGNAL_ARGS)
                         * and exit) and ShutdownDataBase when they are gone.
                         */
                        if (Shutdown >= FastShutdown)
-                       {
-                               errno = save_errno;
-                               return;
-                       }
+                               break;
                        elog(DEBUG, "fast shutdown request");
                        if (DLGetHead(BackendList)) /* let reaper() handle this */
                        {
@@ -1482,14 +1457,12 @@ pmdie(SIGNAL_ARGS)
                                        elog(DEBUG, "aborting any active transactions");
                                        SignalChildren(SIGTERM);
                                }
-                               errno = save_errno;
-                               return;
+                               break;
                        }
                        if (Shutdown > NoShutdown)
                        {
                                Shutdown = FastShutdown;
-                               errno = save_errno;
-                               return;
+                               break;
                        }
                        Shutdown = FastShutdown;
 
@@ -1498,10 +1471,7 @@ pmdie(SIGNAL_ARGS)
                         */
                        if (StartupPID > 0 || FatalError)       /* let reaper() handle
                                                                                                 * this */
-                       {
-                               errno = save_errno;
-                               return;
-                       }
+                               break;
                        if (ShutdownPID > 0)
                        {
                                elog(REALLYFATAL, "shutdown process %d already running",
@@ -1510,8 +1480,7 @@ pmdie(SIGNAL_ARGS)
                        }
 
                        ShutdownPID = ShutdownDataBase();
-                       errno = save_errno;
-                       return;
+                       break;
 
                case SIGQUIT:
 
@@ -1528,11 +1497,13 @@ pmdie(SIGNAL_ARGS)
                                kill(StartupPID, SIGQUIT);
                        if (DLGetHead(BackendList))
                                SignalChildren(SIGQUIT);
+                       ExitPostmaster(0);
                        break;
        }
 
-       /* exit postmaster */
-       ExitPostmaster(0);
+       PG_SETMASK(&UnBlockSig);
+
+       errno = save_errno;
 }
 
 /*
@@ -1542,10 +1513,8 @@ static void
 reaper(SIGNAL_ARGS)
 {
        int                     save_errno = errno;
-
 #ifdef HAVE_WAITPID
        int                     status;                 /* backend exit status */
-
 #else
        union wait      status;                 /* backend exit status */
 #endif
@@ -1553,8 +1522,6 @@ reaper(SIGNAL_ARGS)
        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)
                elog(DEBUG, "reaping dead processes");
@@ -1640,8 +1607,7 @@ reaper(SIGNAL_ARGS)
                        CheckPointPID = 0;
                        checkpointed = time(NULL);
 
-                       errno = save_errno;
-                       return;
+                       goto reaper_done;
                }
 
                CleanupProc(pid, exitstatus);
@@ -1654,35 +1620,29 @@ reaper(SIGNAL_ARGS)
                 * StartupDataBase.
                 */
                if (DLGetHead(BackendList) || StartupPID > 0 || ShutdownPID > 0)
-               {
-                       errno = save_errno;
-                       return;
-               }
+                       goto reaper_done;
                elog(DEBUG, "all server processes terminated; reinitializing shared memory and semaphores");
 
                shmem_exit(0);
                reset_shared(PostPortNumber);
 
                StartupPID = StartupDataBase();
-               errno = save_errno;
-               return;
+
+               goto reaper_done;
        }
 
        if (Shutdown > NoShutdown)
        {
                if (DLGetHead(BackendList))
-               {
-                       errno = save_errno;
-                       return;
-               }
+                       goto reaper_done;
                if (StartupPID > 0 || ShutdownPID > 0)
-               {
-                       errno = save_errno;
-                       return;
-               }
+                       goto reaper_done;
                ShutdownPID = ShutdownDataBase();
        }
 
+reaper_done:
+       PG_SETMASK(&UnBlockSig);
+
        errno = save_errno;
 }
 
@@ -2260,26 +2220,70 @@ ExitPostmaster(int status)
        proc_exit(status);
 }
 
-/* Request to schedule a checkpoint (no-op if one is currently running) */
+/*
+ * sigusr1_handler - handle signal conditions from child processes
+ */
 static void
-schedule_checkpoint(SIGNAL_ARGS)
+sigusr1_handler(SIGNAL_ARGS)
 {
        int                     save_errno = errno;
 
        PG_SETMASK(&BlockSig);
 
-       /* Ignore request if checkpointing is currently disabled */
-       if (CheckPointPID == 0 && checkpointed &&
-               Shutdown == NoShutdown && !FatalError && random_seed != 0)
+       if (CheckPostmasterSignal(PMSIGNAL_DO_CHECKPOINT))
        {
-               CheckPointPID = CheckPointDataBase();
-               /* note: if fork fails, CheckPointPID stays 0; nothing happens */
+               /*
+                * Request to schedule a checkpoint
+                *
+                * Ignore request if checkpoint is already running or
+                * checkpointing is currently disabled
+                */
+               if (CheckPointPID == 0 && checkpointed &&
+                       Shutdown == NoShutdown && !FatalError && random_seed != 0)
+               {
+                       CheckPointPID = CheckPointDataBase();
+                       /* note: if fork fails, CheckPointPID stays 0; nothing happens */
+               }
+       }
+
+       if (CheckPostmasterSignal(PMSIGNAL_PASSWORD_CHANGE))
+       {
+               /*
+                * Password file has changed.
+                */
+               load_password_cache();
        }
 
+       if (CheckPostmasterSignal(PMSIGNAL_WAKEN_CHILDREN))
+       {
+               /*
+                * Send SIGUSR2 to all children (triggers AsyncNotifyHandler).
+                * See storage/ipc/sinvaladt.c for the use of this.
+                */
+               if (Shutdown == NoShutdown)
+                       SignalChildren(SIGUSR2);
+       }
+
+       PG_SETMASK(&UnBlockSig);
+
        errno = save_errno;
 }
 
 
+/*
+ * Dummy signal handler
+ *
+ * We use this for signals that we don't actually use in the postmaster,
+ * but we do use in backends.  If we SIG_IGN such signals in the postmaster,
+ * then a newly started backend might drop a signal that arrives before it's
+ * able to reconfigure its signal processing.  (See notes in postgres.c.)
+ */
+static void
+dummy_handler(SIGNAL_ARGS)
+{
+}
+
+
 /*
  * CharRemap: given an int in range 0..61, produce textual encoding of it
  * per crypt(3) conventions.
index 585ae7f6eff0dd3107d3a655271acebddb73e3ee..960097b1d18a9883deb71d9c633bd0d0220fc8b0 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Makefile for storage/ipc
 #
-# $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.16 2001/09/27 19:10:02 tgl Exp $
+# $Header: /cvsroot/pgsql/src/backend/storage/ipc/Makefile,v 1.17 2001/11/04 19:55:31 tgl Exp $
 #
 
 subdir = src/backend/storage/ipc
@@ -15,7 +15,7 @@ override CFLAGS+= -fno-inline
 endif
 endif
 
-OBJS = ipc.o ipci.o shmem.o shmqueue.o sinval.o sinvaladt.o
+OBJS = ipc.o ipci.o pmsignal.o shmem.o shmqueue.o sinval.o sinvaladt.o
 
 all: SUBSYS.o
 
index cf841a614d3063e9c05b78a0db60d837fde6ee63..9b178883fe45325c7f9c93b0d621c8a228e5144d 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.44 2001/10/25 05:49:42 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.45 2001/11/04 19:55:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,6 +23,7 @@
 #include "storage/freespace.h"
 #include "storage/lmgr.h"
 #include "storage/lwlock.h"
+#include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/sinval.h"
 #include "storage/spin.h"
@@ -121,4 +122,9 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends)
         * Set up free-space map
         */
        InitFreeSpaceMap();
+
+       /*
+        * Set up child-to-postmaster signaling mechanism
+        */
+       PMSignalInit();
 }
diff --git a/src/backend/storage/ipc/pmsignal.c b/src/backend/storage/ipc/pmsignal.c
new file mode 100644 (file)
index 0000000..38c5d73
--- /dev/null
@@ -0,0 +1,86 @@
+/*-------------------------------------------------------------------------
+ *
+ * pmsignal.c
+ *       routines for signaling the postmaster from its child processes
+ *
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/pmsignal.c,v 1.1 2001/11/04 19:55:31 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <signal.h>
+#include <unistd.h>
+
+#include "miscadmin.h"
+#include "storage/pmsignal.h"
+#include "storage/shmem.h"
+
+
+/*
+ * The postmaster is signaled by its children by sending SIGUSR1.  The
+ * specific reason is communicated via flags in shared memory.  We keep
+ * a boolean flag for each possible "reason", so that different reasons
+ * can be signaled by different backends at the same time.  (However,
+ * if the same reason is signaled more than once simultaneously, the
+ * postmaster will observe it only once.)
+ *
+ * The flags are actually declared as "volatile sig_atomic_t" for maximum
+ * portability.  This should ensure that loads and stores of the flag
+ * values are atomic, allowing us to dispense with any explicit locking.
+ */
+
+static volatile sig_atomic_t * PMSignalFlags;
+
+
+/*
+ * PMSignalInit - initialize during shared-memory creation
+ */
+void
+PMSignalInit(void)
+{
+       /* Should be called only once */
+       Assert(!PMSignalFlags);
+
+       PMSignalFlags = (sig_atomic_t *)
+               ShmemAlloc(NUM_PMSIGNALS * sizeof(sig_atomic_t));
+
+       MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t));
+}
+
+/*
+ * SendPostmasterSignal - signal the postmaster from a child process
+ */
+void
+SendPostmasterSignal(PMSignalReason reason)
+{
+       /* If called in a standalone backend, do nothing */
+       if (!IsUnderPostmaster)
+               return;
+       /* Atomically set the proper flag */
+       PMSignalFlags[reason] = true;
+       /* Send signal to postmaster (assume it is our direct parent) */
+       kill(getppid(), SIGUSR1);
+}
+
+/*
+ * CheckPostmasterSignal - check to see if a particular reason has been
+ * signaled, and clear the signal flag.  Should be called by postmaster
+ * after receiving SIGUSR1.
+ */
+bool
+CheckPostmasterSignal(PMSignalReason reason)
+{
+       /* Careful here --- don't clear flag if we haven't seen it set */
+       if (PMSignalFlags[reason])
+       {
+               PMSignalFlags[reason] = false;
+               return true;
+       }
+       return false;
+}
index d05a651097f672af10e7fd1b4734a4161de0f7f4..35931f00a14eaac1f58d658a7c3d0be1064fdb80 100644 (file)
@@ -8,17 +8,15 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.41 2001/09/29 04:02:24 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.42 2001/11/04 19:55:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
-#include <signal.h>
-#include <unistd.h>
-
 #include "miscadmin.h"
 #include "storage/backendid.h"
+#include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/sinvaladt.h"
 
@@ -205,11 +203,11 @@ SIInsertDataEntry(SISeg *segP, SharedInvalidationMessage *data)
 
        /*
         * Try to prevent table overflow.  When the table is 70% full send a
-        * SIGUSR2 (ordinarily a NOTIFY signal) to the postmaster, which will
-        * send it back to all the backends.  This will force idle backends to
-        * execute a transaction to look through pg_listener for NOTIFY
-        * messages, and as a byproduct of the transaction start they will
-        * read SI entries.
+        * WAKEN_CHILDREN request to the postmaster.  The postmaster will send
+        * a SIGUSR2 signal (ordinarily a NOTIFY signal) to all the backends.
+        * This will force idle backends to execute a transaction to look through
+        * pg_listener for NOTIFY messages, and as a byproduct of the transaction
+        * start they will read SI entries.
         *
         * This should never happen if all the backends are actively executing
         * queries, but if a backend is sitting idle then it won't be starting
@@ -222,7 +220,7 @@ SIInsertDataEntry(SISeg *segP, SharedInvalidationMessage *data)
        {
                if (DebugLvl >= 1)
                        elog(DEBUG, "SIInsertDataEntry: table is 70%% full, signaling postmaster");
-               kill(getppid(), SIGUSR2);
+               SendPostmasterSignal(PMSIGNAL_WAKEN_CHILDREN);
        }
 
        /*
diff --git a/src/include/storage/pmsignal.h b/src/include/storage/pmsignal.h
new file mode 100644 (file)
index 0000000..f86c066
--- /dev/null
@@ -0,0 +1,39 @@
+/*-------------------------------------------------------------------------
+ *
+ * pmsignal.h
+ *       routines for signaling the postmaster from its child processes
+ *
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: pmsignal.h,v 1.1 2001/11/04 19:55:31 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PMSIGNAL_H
+#define PMSIGNAL_H
+
+/*
+ * Reasons for signaling the postmaster.  We can cope with simultaneous
+ * signals for different reasons.  If the same reason is signaled multiple
+ * times in quick succession, however, the postmaster is likely to observe
+ * only one notification of it.  This is okay for the present uses.
+ */
+typedef enum
+{
+       PMSIGNAL_DO_CHECKPOINT,         /* request to start a checkpoint */
+       PMSIGNAL_PASSWORD_CHANGE,       /* pg_pwd file has changed */
+       PMSIGNAL_WAKEN_CHILDREN,        /* send a NOTIFY signal to all backends */
+
+       NUM_PMSIGNALS                           /* Must be last value of enum! */
+} PMSignalReason;
+
+/*
+ * prototypes for functions in pmsignal.c
+ */
+extern void PMSignalInit(void);
+extern void SendPostmasterSignal(PMSignalReason reason);
+extern bool CheckPostmasterSignal(PMSignalReason reason);
+
+#endif  /* PMSIGNAL_H */