diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 5a0f852b6fef0a40769ae430b2bf38edd9cd60b5..ff31e5f040e6972820a8621994e76b4e4dc50725 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.250 2009/02/18 15:58:41 heikki Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.251 2009/07/31 20:26:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,7 @@
 #include "storage/bufmgr.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
+#include "storage/procsignal.h"
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -388,6 +389,19 @@ AuxiliaryProcessMain(int argc, char *argv[])
 		InitAuxiliaryProcess();
 #endif
 
+		/*
+		 * Assign the ProcSignalSlot for an auxiliary process.  Since it
+		 * doesn't have a BackendId, the slot is statically allocated based on
+		 * the auxiliary process type (auxType).  Backends use slots indexed
+		 * in the range from 1 to MaxBackends (inclusive), so we use
+		 * MaxBackends + AuxProcType + 1 as the index of the slot for an
+		 * auxiliary process.
+		 *
+		 * This will need rethinking if we ever want more than one of a
+		 * particular auxiliary process type.
+		 */
+		ProcSignalInit(MaxBackends + auxType + 1);
+
 		/* finish setting up bufmgr.c */
 		InitBufferPoolBackend();
 
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index de09872cd7ee637c1add091ab53a6715991de991..21c7bbe726e1ab40be37d26b63e5f95fc7828815 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
- *	  $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.148 2009/07/21 20:24:51 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/async.c,v 1.149 2009/07/31 20:26:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,14 +35,15 @@
  *	  If the listenerPID in a matching tuple is ours, we just send a notify
  *	  message to our own front end.  If it is not ours, and "notification"
  *	  is not already nonzero, we set notification to our own PID and send a
- *	  SIGUSR2 signal to the receiving process (indicated by listenerPID).
+ *	  PROCSIG_NOTIFY_INTERRUPT signal to the receiving process (indicated by
+ *	  listenerPID).
  *	  BTW: if the signal operation fails, we presume that the listener backend
  *	  crashed without removing this tuple, and remove the tuple for it.
  *
- * 4. Upon receipt of a SIGUSR2 signal, the signal handler can call inbound-
- *	  notify processing immediately if this backend is idle (ie, it is
- *	  waiting for a frontend command and is not within a transaction block).
- *	  Otherwise the handler may only set a flag, which will cause the
+ * 4. Upon receipt of a PROCSIG_NOTIFY_INTERRUPT signal, the signal handler
+ *	  can call inbound-notify processing immediately if this backend is idle
+ *	  (ie, it is waiting for a frontend command and is not within a transaction
+ *	  block).  Otherwise the handler may only set a flag, which will cause the
  *	  processing to occur just before we next go idle.
  *
  * 5. Inbound-notify processing consists of scanning pg_listener for tuples
@@ -95,6 +96,7 @@
 #include "libpq/pqformat.h"
 #include "miscadmin.h"
 #include "storage/ipc.h"
+#include "storage/procsignal.h"
 #include "storage/sinval.h"
 #include "tcop/tcopprot.h"
 #include "utils/builtins.h"
@@ -634,12 +636,17 @@ Send_Notify(Relation lRel)
 
 			/*
 			 * If someone has already notified this listener, we don't bother
-			 * modifying the table, but we do still send a SIGUSR2 signal,
-			 * just in case that backend missed the earlier signal for some
-			 * reason.	It's OK to send the signal first, because the other
-			 * guy can't read pg_listener until we unlock it.
+			 * modifying the table, but we do still send a NOTIFY_INTERRUPT
+			 * signal, just in case that backend missed the earlier signal for
+			 * some reason.  It's OK to send the signal first, because the
+			 * other guy can't read pg_listener until we unlock it.
+			 *
+			 * Note: we don't have the other guy's BackendId available, so
+			 * this will incur a search of the ProcSignal table.  That's
+			 * probably not worth worrying about.
 			 */
-			if (kill(listenerPID, SIGUSR2) < 0)
+			if (SendProcSignal(listenerPID, PROCSIG_NOTIFY_INTERRUPT,
+							   InvalidBackendId) < 0)
 			{
 				/*
 				 * Get rid of pg_listener entry if it refers to a PID that no
@@ -777,24 +784,22 @@ AtSubAbort_Notify(void)
 }
 
 /*
- * NotifyInterruptHandler
+ * HandleNotifyInterrupt
  *
- *		This is the signal handler for SIGUSR2.
+ *		This is called when PROCSIG_NOTIFY_INTERRUPT is received.
  *
  *		If we are idle (notifyInterruptEnabled is set), we can safely invoke
  *		ProcessIncomingNotify directly.  Otherwise, just set a flag
  *		to do it later.
  */
 void
-NotifyInterruptHandler(SIGNAL_ARGS)
+HandleNotifyInterrupt(void)
 {
-	int			save_errno = errno;
-
 	/*
-	 * Note: this is a SIGNAL HANDLER.	You must be very wary what you do
-	 * here. Some helpful soul had this routine sprinkled with TPRINTFs, which
-	 * would likely lead to corruption of stdio buffers if they were ever
-	 * turned on.
+	 * Note: this is called by a SIGNAL HANDLER. You must be very wary what
+	 * you do here. Some helpful soul had this routine sprinkled with
+	 * TPRINTFs, which would likely lead to corruption of stdio buffers if
+	 * they were ever turned on.
 	 */
 
 	/* Don't joggle the elbow of proc_exit */
@@ -815,7 +820,7 @@ NotifyInterruptHandler(SIGNAL_ARGS)
 
 		/*
 		 * I'm not sure whether some flavors of Unix might allow another
-		 * SIGUSR2 occurrence to recursively interrupt this routine. To cope
+		 * SIGUSR1 occurrence to recursively interrupt this routine. To cope
 		 * with the possibility, we do the same sort of dance that
 		 * EnableNotifyInterrupt must do --- see that routine for comments.
 		 */
@@ -831,12 +836,12 @@ NotifyInterruptHandler(SIGNAL_ARGS)
 			{
 				/* Here, it is finally safe to do stuff. */
 				if (Trace_notify)
-					elog(DEBUG1, "NotifyInterruptHandler: perform async notify");
+					elog(DEBUG1, "HandleNotifyInterrupt: perform async notify");
 
 				ProcessIncomingNotify();
 
 				if (Trace_notify)
-					elog(DEBUG1, "NotifyInterruptHandler: done");
+					elog(DEBUG1, "HandleNotifyInterrupt: done");
 			}
 		}
 
@@ -854,8 +859,6 @@ NotifyInterruptHandler(SIGNAL_ARGS)
 		 */
 		notifyInterruptOccurred = 1;
 	}
-
-	errno = save_errno;
 }
 
 /*
@@ -922,8 +925,8 @@ EnableNotifyInterrupt(void)
  *		a frontend command.  Signal handler execution of inbound notifies
  *		is disabled until the next EnableNotifyInterrupt call.
  *
- *		The SIGUSR1 signal handler also needs to call this, so as to
- *		prevent conflicts if one signal interrupts the other.  So we
+ *		The PROCSIG_CATCHUP_INTERRUPT signal handler also needs to call this,
+ *		so as to prevent conflicts if one signal interrupts the other.  So we
  *		must return the previous state of the flag.
  */
 bool
@@ -940,8 +943,8 @@ DisableNotifyInterrupt(void)
  * ProcessIncomingNotify
  *
  *		Deal with arriving NOTIFYs from other backends.
- *		This is called either directly from the SIGUSR2 signal handler,
- *		or the next time control reaches the outer idle loop.
+ *		This is called either directly from the PROCSIG_NOTIFY_INTERRUPT
+ *		signal handler, or the next time control reaches the outer idle loop.
  *		Scan pg_listener for arriving notifies, report them to my front end,
  *		and clear the notification field in pg_listener until next time.
  *
@@ -961,7 +964,7 @@ ProcessIncomingNotify(void)
 				nulls[Natts_pg_listener];
 	bool		catchup_enabled;
 
-	/* Must prevent SIGUSR1 interrupt while I am running */
+	/* Must prevent catchup interrupt while I am running */
 	catchup_enabled = DisableCatchupInterrupt();
 
 	if (Trace_notify)
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index a5388678d6c6606d54463dcd3bd04945d9202d4d..34c4a4a4283c3c6d989637626bf0edafafd86a2b 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -55,7 +55,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.99 2009/06/12 16:17:29 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.100 2009/07/31 20:26:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -91,6 +91,7 @@
 #include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
+#include "storage/procsignal.h"
 #include "storage/sinvaladt.h"
 #include "tcop/tcopprot.h"
 #include "utils/dynahash.h"
@@ -436,7 +437,6 @@ AutoVacLauncherMain(int argc, char *argv[])
 
 	pqsignal(SIGPIPE, SIG_IGN);
 	pqsignal(SIGUSR1, avl_sigusr1_handler);
-	/* We don't listen for async notifies */
 	pqsignal(SIGUSR2, SIG_IGN);
 	pqsignal(SIGFPE, FloatExceptionHandler);
 	pqsignal(SIGCHLD, SIG_DFL);
@@ -1322,7 +1322,7 @@ avl_sighup_handler(SIGNAL_ARGS)
 	got_SIGHUP = true;
 }
 
-/* SIGUSR1: a worker is up and running, or just finished */
+/* SIGUSR1: a worker is up and running, or just finished, or failed to fork */
 static void
 avl_sigusr1_handler(SIGNAL_ARGS)
 {
@@ -1501,8 +1501,7 @@ AutoVacWorkerMain(int argc, char *argv[])
 	pqsignal(SIGALRM, handle_sig_alarm);
 
 	pqsignal(SIGPIPE, SIG_IGN);
-	pqsignal(SIGUSR1, CatchupInterruptHandler);
-	/* We don't listen for async notifies */
+	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
 	pqsignal(SIGUSR2, SIG_IGN);
 	pqsignal(SIGFPE, FloatExceptionHandler);
 	pqsignal(SIGCHLD, SIG_DFL);
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 831ea9478a74e0fd775a611a75d413568eb6ddbb..bcdb5d7bb75a3c920a6727417ca0ebbf79998102 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -38,7 +38,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.62 2009/06/26 20:29:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/bgwriter.c,v 1.63 2009/07/31 20:26:22 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -223,7 +223,7 @@ BackgroundWriterMain(void)
 	 * tell us it's okay to shut down (via SIGUSR2).
 	 *
 	 * SIGUSR1 is presently unused; keep it spare in case someday we want this
-	 * process to participate in sinval messaging.
+	 * process to participate in ProcSignal signalling.
 	 */
 	pqsignal(SIGHUP, BgSigHupHandler);	/* set flag to read config file */
 	pqsignal(SIGINT, ReqCheckpointHandler);		/* request checkpoint */
@@ -231,7 +231,7 @@ BackgroundWriterMain(void)
 	pqsignal(SIGQUIT, bg_quickdie);		/* hard crash time */
 	pqsignal(SIGALRM, SIG_IGN);
 	pqsignal(SIGPIPE, SIG_IGN);
-	pqsignal(SIGUSR1, SIG_IGN); /* reserve for sinval */
+	pqsignal(SIGUSR1, SIG_IGN); /* reserve for ProcSignal */
 	pqsignal(SIGUSR2, ReqShutdownHandler);		/* request shutdown */
 
 	/*
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 9e08a5b710e5c81db2da7aa550709439975f1981..7f13e682a5c1d3fa350b5cc471eedb464b987be0 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -34,7 +34,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/walwriter.c,v 1.7 2009/06/11 14:49:01 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/walwriter.c,v 1.8 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -113,7 +113,7 @@ WalWriterMain(void)
 	pqsignal(SIGQUIT, wal_quickdie);	/* hard crash time */
 	pqsignal(SIGALRM, SIG_IGN);
 	pqsignal(SIGPIPE, SIG_IGN);
-	pqsignal(SIGUSR1, SIG_IGN); /* reserve for sinval */
+	pqsignal(SIGUSR1, SIG_IGN); /* reserve for ProcSignal */
 	pqsignal(SIGUSR2, SIG_IGN); /* not used */
 
 	/*
diff --git a/src/backend/storage/ipc/Makefile b/src/backend/storage/ipc/Makefile
index cc74f8812bbdfd4c360bc176e5d8c7ce7a419cb9..20ac1e75e45d6db67c350c50c0fe35566c9c7463 100644
--- a/src/backend/storage/ipc/Makefile
+++ b/src/backend/storage/ipc/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for storage/ipc
 #
-# $PostgreSQL: pgsql/src/backend/storage/ipc/Makefile,v 1.21 2008/02/19 10:30:08 petere Exp $
+# $PostgreSQL: pgsql/src/backend/storage/ipc/Makefile,v 1.22 2009/07/31 20:26:23 tgl Exp $
 #
 
 subdir = src/backend/storage/ipc
@@ -15,7 +15,7 @@ override CFLAGS+= -fno-inline
 endif
 endif
 
-OBJS = ipc.o ipci.o pmsignal.o procarray.o shmem.o shmqueue.o \
+OBJS = ipc.o ipci.o pmsignal.o procarray.o procsignal.o shmem.o shmqueue.o \
 	sinval.o sinvaladt.o
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c
index 281215d2189addc2536a429fbbc09321397a7805..bd4f168bfb0cc6fed56f509aecac879a1c2a8a6c 100644
--- a/src/backend/storage/ipc/ipci.c
+++ b/src/backend/storage/ipc/ipci.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.100 2009/05/05 19:59:00 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.101 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,6 +30,7 @@
 #include "storage/pg_shmem.h"
 #include "storage/pmsignal.h"
 #include "storage/procarray.h"
+#include "storage/procsignal.h"
 #include "storage/sinvaladt.h"
 #include "storage/spin.h"
 
@@ -112,6 +113,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 		size = add_size(size, BackendStatusShmemSize());
 		size = add_size(size, SInvalShmemSize());
 		size = add_size(size, PMSignalShmemSize());
+		size = add_size(size, ProcSignalShmemSize());
 		size = add_size(size, BgWriterShmemSize());
 		size = add_size(size, AutoVacuumShmemSize());
 		size = add_size(size, BTreeShmemSize());
@@ -208,6 +210,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
 	 * Set up interprocess signaling mechanisms
 	 */
 	PMSignalShmemInit();
+	ProcSignalShmemInit();
 	BgWriterShmemInit();
 	AutoVacuumShmemInit();
 
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
new file mode 100644
index 0000000000000000000000000000000000000000..9da2c5201e771b38e343eea5bde62d435cb6b847
--- /dev/null
+++ b/src/backend/storage/ipc/procsignal.c
@@ -0,0 +1,262 @@
+/*-------------------------------------------------------------------------
+ *
+ * procsignal.c
+ *	  Routines for interprocess signalling
+ *
+ *
+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/procsignal.c,v 1.1 2009/07/31 20:26:23 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <signal.h>
+#include <unistd.h>
+
+#include "bootstrap/bootstrap.h"
+#include "commands/async.h"
+#include "miscadmin.h"
+#include "storage/ipc.h"
+#include "storage/procsignal.h"
+#include "storage/shmem.h"
+#include "storage/sinval.h"
+
+
+/*
+ * The SIGUSR1 signal is multiplexed to support signalling multiple event
+ * types. 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 to a process concurrently.  (However, if the same
+ * reason is signaled more than once nearly simultaneously, the process may
+ * observe it only once.)
+ *
+ * Each process that wants to receive signals registers its process ID 
+ * in the ProcSignalSlots array. The array is indexed by backend ID to make
+ * slot allocation simple, and to avoid having to search the array when you
+ * know the backend ID of the process you're signalling.  (We do support
+ * signalling without backend ID, but it's a bit less efficient.)
+ * 
+ * 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.
+ */
+typedef struct
+{
+	pid_t		pss_pid;
+	sig_atomic_t pss_signalFlags[NUM_PROCSIGNALS];
+} ProcSignalSlot;
+
+/*
+ * We reserve a slot for each possible BackendId, plus one for each
+ * possible auxiliary process type.  (This scheme assumes there is not
+ * more than one of any auxiliary process type at a time.)
+ */
+#define NumProcSignalSlots  (MaxBackends + NUM_AUXPROCTYPES)
+
+static ProcSignalSlot *ProcSignalSlots = NULL;
+static volatile ProcSignalSlot *MyProcSignalSlot = NULL;
+
+static bool CheckProcSignal(ProcSignalReason reason);
+static void CleanupProcSignalState(int status, Datum arg);
+
+/*
+ * ProcSignalShmemInit
+ *		Compute space needed for procsignal's shared memory
+ */
+Size
+ProcSignalShmemSize(void)
+{
+	return NumProcSignalSlots * sizeof(ProcSignalSlot);
+}
+
+/*
+ * ProcSignalShmemInit
+ *		Allocate and initialize procsignal's shared memory
+ */
+void
+ProcSignalShmemInit(void)
+{
+	Size		size = ProcSignalShmemSize();
+	bool		found;
+
+	ProcSignalSlots = (ProcSignalSlot *)
+		ShmemInitStruct("ProcSignalSlots", size, &found);
+
+	/* If we're first, set everything to zeroes */
+	if (!found)
+		MemSet(ProcSignalSlots, 0, size);
+}
+
+/*
+ * ProcSignalInit
+ *		Register the current process in the procsignal array
+ *
+ * The passed index should be my BackendId if the process has one,
+ * or MaxBackends + aux process type if not.
+ */
+void
+ProcSignalInit(int pss_idx)
+{
+	volatile ProcSignalSlot *slot;
+
+	Assert(pss_idx >= 1 && pss_idx <= NumProcSignalSlots);
+
+	slot = &ProcSignalSlots[pss_idx - 1];
+
+	/* sanity check */
+	if (slot->pss_pid != 0)
+		elog(LOG, "process %d taking over ProcSignal slot %d, but it's not empty",
+			 MyProcPid, pss_idx);
+
+	/* Clear out any leftover signal reasons */
+	MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t));
+
+	/* Mark slot with my PID */
+	slot->pss_pid = MyProcPid;
+
+	/* Remember slot location for CheckProcSignal */
+	MyProcSignalSlot = slot;
+
+	/* Set up to release the slot on process exit */
+	on_shmem_exit(CleanupProcSignalState, Int32GetDatum(pss_idx));
+}
+
+/*
+ * CleanupProcSignalState
+ *		Remove current process from ProcSignalSlots
+ *
+ * This function is called via on_shmem_exit() during backend shutdown.
+ */
+static void
+CleanupProcSignalState(int status, Datum arg)
+{
+	int			pss_idx = DatumGetInt32(arg);
+	volatile ProcSignalSlot *slot;
+
+	slot = &ProcSignalSlots[pss_idx - 1];
+	Assert(slot == MyProcSignalSlot);
+
+	/* sanity check */
+	if (slot->pss_pid != MyProcPid)
+	{
+		/*
+		 * don't ERROR here. We're exiting anyway, and don't want to
+		 * get into infinite loop trying to exit
+		 */
+		elog(LOG, "process %d releasing ProcSignal slot %d, but it contains %d",
+			 MyProcPid, pss_idx, (int) slot->pss_pid);
+		return;					/* XXX better to zero the slot anyway? */
+	}
+
+	slot->pss_pid = 0;
+}
+
+/*
+ * SendProcSignal
+ *		Send a signal to a Postgres process
+ *
+ * Providing backendId is optional, but it will speed up the operation.
+ *
+ * On success (a signal was sent), zero is returned.
+ * On error, -1 is returned, and errno is set (typically to ESRCH or EPERM).
+ *
+ * Not to be confused with ProcSendSignal
+ */
+int
+SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
+{
+	volatile ProcSignalSlot *slot;
+
+	if (backendId != InvalidBackendId)
+	{
+		slot = &ProcSignalSlots[backendId - 1];
+
+		/*
+		 * Note: Since there's no locking, it's possible that the target
+		 * process detaches from shared memory and exits right after this
+		 * test, before we set the flag and send signal. And the signal slot
+		 * might even be recycled by a new process, so it's remotely possible
+		 * that we set a flag for a wrong process. That's OK, all the signals
+		 * are such that no harm is done if they're mistakenly fired.
+		 */
+		if (slot->pss_pid == pid)
+		{
+			/* Atomically set the proper flag */
+			slot->pss_signalFlags[reason] = true;
+			/* Send signal */
+			return kill(pid, SIGUSR1);
+		}
+	}
+	else
+	{
+		/*
+		 * BackendId not provided, so search the array using pid.  We search
+		 * the array back to front so as to reduce search overhead.  Passing
+		 * InvalidBackendId means that the target is most likely an auxiliary
+		 * process, which will have a slot near the end of the array.
+		 */
+		int		i;
+
+		for (i = NumProcSignalSlots - 1; i >= 0; i--)
+		{
+			slot = &ProcSignalSlots[i];
+
+			if (slot->pss_pid == pid)
+			{
+				/* the above note about race conditions applies here too */
+
+				/* Atomically set the proper flag */
+				slot->pss_signalFlags[reason] = true;
+				/* Send signal */
+				return kill(pid, SIGUSR1);
+			}
+		}
+	}
+
+	errno = ESRCH;
+	return -1;
+}
+
+/*
+ * CheckProcSignal - check to see if a particular reason has been
+ * signaled, and clear the signal flag.  Should be called after receiving
+ * SIGUSR1.
+ */
+static bool
+CheckProcSignal(ProcSignalReason reason)
+{
+	volatile ProcSignalSlot *slot = MyProcSignalSlot;
+
+	if (slot != NULL)
+	{
+		/* Careful here --- don't clear flag if we haven't seen it set */
+		if (slot->pss_signalFlags[reason])
+		{
+			slot->pss_signalFlags[reason] = false;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/*
+ * procsignal_sigusr1_handler - handle SIGUSR1 signal.
+ */
+void
+procsignal_sigusr1_handler(SIGNAL_ARGS)
+{
+	int		save_errno = errno;
+
+	if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
+		HandleCatchupInterrupt();
+
+	if (CheckProcSignal(PROCSIG_NOTIFY_INTERRUPT))
+		HandleNotifyInterrupt();
+
+	errno = save_errno;
+}
diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c
index 3f063989e0c4c9cf4d0fbff35ed86ab51561a541..1b6f3b2fc4421be40a841b1c0ff022f0460e9034 100644
--- a/src/backend/storage/ipc/sinval.c
+++ b/src/backend/storage/ipc/sinval.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.90 2009/06/11 14:49:02 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.91 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,8 +26,8 @@
  * Because backends sitting idle will not be reading sinval events, we
  * need a way to give an idle backend a swift kick in the rear and make
  * it catch up before the sinval queue overflows and forces it to go
- * through a cache reset exercise.	This is done by sending SIGUSR1
- * to any backend that gets too far behind.
+ * through a cache reset exercise.	This is done by sending
+ * PROCSIG_CATCHUP_INTERRUPT to any backend that gets too far behind.
  *
  * State for catchup events consists of two flags: one saying whether
  * the signal handler is currently allowed to call ProcessCatchupEvent
@@ -145,9 +145,9 @@ ReceiveSharedInvalidMessages(
 
 
 /*
- * CatchupInterruptHandler
+ * HandleCatchupInterrupt
  *
- * This is the signal handler for SIGUSR1.
+ * This is called when PROCSIG_CATCHUP_INTERRUPT is received.
  *
  * If we are idle (catchupInterruptEnabled is set), we can safely
  * invoke ProcessCatchupEvent directly.  Otherwise, just set a flag
@@ -157,13 +157,11 @@ ReceiveSharedInvalidMessages(
  * since there's no longer any reason to do anything.)
  */
 void
-CatchupInterruptHandler(SIGNAL_ARGS)
+HandleCatchupInterrupt(void)
 {
-	int			save_errno = errno;
-
 	/*
-	 * Note: this is a SIGNAL HANDLER.	You must be very wary what you do
-	 * here.
+	 * Note: this is called by a SIGNAL HANDLER. You must be very wary what
+	 * you do here.
 	 */
 
 	/* Don't joggle the elbow of proc_exit */
@@ -217,8 +215,6 @@ CatchupInterruptHandler(SIGNAL_ARGS)
 		 */
 		catchupInterruptOccurred = 1;
 	}
-
-	errno = save_errno;
 }
 
 /*
@@ -273,8 +269,8 @@ EnableCatchupInterrupt(void)
  * a frontend command.	Signal handler execution of catchup events
  * is disabled until the next EnableCatchupInterrupt call.
  *
- * The SIGUSR2 signal handler also needs to call this, so as to
- * prevent conflicts if one signal interrupts the other.  So we
+ * The PROCSIG_NOTIFY_INTERRUPT signal handler also needs to call this,
+ * so as to prevent conflicts if one signal interrupts the other.  So we
  * must return the previous state of the flag.
  */
 bool
@@ -290,18 +286,19 @@ DisableCatchupInterrupt(void)
 /*
  * ProcessCatchupEvent
  *
- * Respond to a catchup event (SIGUSR1) from another backend.
+ * Respond to a catchup event (PROCSIG_CATCHUP_INTERRUPT) from another
+ * backend.
  *
- * This is called either directly from the SIGUSR1 signal handler,
- * or the next time control reaches the outer idle loop (assuming
- * there's still anything to do by then).
+ * This is called either directly from the PROCSIG_CATCHUP_INTERRUPT
+ * signal handler, or the next time control reaches the outer idle loop
+ * (assuming there's still anything to do by then).
  */
 static void
 ProcessCatchupEvent(void)
 {
 	bool		notify_enabled;
 
-	/* Must prevent SIGUSR2 interrupt while I am running */
+	/* Must prevent notify interrupt while I am running */
 	notify_enabled = DisableNotifyInterrupt();
 
 	/*
diff --git a/src/backend/storage/ipc/sinvaladt.c b/src/backend/storage/ipc/sinvaladt.c
index fcd1e42a7f6d5a004d10f941e811ce53ef5f287e..dfa0ad7b5eb0174881ccaeca36e22aaef0fac2bf 100644
--- a/src/backend/storage/ipc/sinvaladt.c
+++ b/src/backend/storage/ipc/sinvaladt.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.78 2009/06/11 14:49:02 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.79 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "storage/backendid.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
+#include "storage/procsignal.h"
 #include "storage/shmem.h"
 #include "storage/sinvaladt.h"
 #include "storage/spin.h"
@@ -118,7 +119,7 @@
  * we exceed CLEANUP_MIN.  Should be a power of 2 for speed.
  *
  * SIG_THRESHOLD: the minimum number of messages a backend must have fallen
- * behind before we'll send it SIGUSR1.
+ * behind before we'll send it PROCSIG_CATCHUP_INTERRUPT.
  *
  * WRITE_QUANTUM: the max number of messages to push into the buffer per
  * iteration of SIInsertDataEntries.  Noncritical but should be less than
@@ -551,7 +552,7 @@ SIGetDataEntries(SharedInvalidationMessage *data, int datasize)
  * minFree is the minimum number of message slots to make free.
  *
  * Possible side effects of this routine include marking one or more
- * backends as "reset" in the array, and sending a catchup interrupt (SIGUSR1)
+ * backends as "reset" in the array, and sending PROCSIG_CATCHUP_INTERRUPT
  * to some backend that seems to be getting too far behind.  We signal at
  * most one backend at a time, for reasons explained at the top of the file.
  *
@@ -644,18 +645,20 @@ SICleanupQueue(bool callerHasWriteLock, int minFree)
 		segP->nextThreshold = (numMsgs / CLEANUP_QUANTUM + 1) * CLEANUP_QUANTUM;
 
 	/*
-	 * Lastly, signal anyone who needs a catchup interrupt.  Since kill()
-	 * might not be fast, we don't want to hold locks while executing it.
+	 * Lastly, signal anyone who needs a catchup interrupt.  Since
+	 * SendProcSignal() might not be fast, we don't want to hold locks while
+	 * executing it.
 	 */
 	if (needSig)
 	{
 		pid_t		his_pid = needSig->procPid;
+		BackendId	his_backendId = (needSig - &segP->procState[0]) + 1;
 
 		needSig->signaled = true;
 		LWLockRelease(SInvalReadLock);
 		LWLockRelease(SInvalWriteLock);
 		elog(DEBUG4, "sending sinval catchup signal to PID %d", (int) his_pid);
-		kill(his_pid, SIGUSR1);
+		SendProcSignal(his_pid, PROCSIG_CATCHUP_INTERRUPT, his_backendId);
 		if (callerHasWriteLock)
 			LWLockAcquire(SInvalWriteLock, LW_EXCLUSIVE);
 	}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 43e912f5cff3a044e40e7a2c3e0c50b42355dcff..42e7f79f70fcb176df063c63fecfb21d5ded1d7d 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.568 2009/06/18 10:08:08 heikki Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.569 2009/07/31 20:26:23 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -59,6 +59,7 @@
 #include "storage/bufmgr.h"
 #include "storage/ipc.h"
 #include "storage/proc.h"
+#include "storage/procsignal.h"
 #include "storage/sinval.h"
 #include "tcop/fastpath.h"
 #include "tcop/pquery.h"
@@ -3221,8 +3222,8 @@ PostgresMain(int argc, char *argv[], const char *username)
 	 * of output during who-knows-what operation...
 	 */
 	pqsignal(SIGPIPE, SIG_IGN);
-	pqsignal(SIGUSR1, CatchupInterruptHandler);
-	pqsignal(SIGUSR2, NotifyInterruptHandler);
+	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
+	pqsignal(SIGUSR2, SIG_IGN);
 	pqsignal(SIGFPE, FloatExceptionHandler);
 
 	/*
diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c
index bdb2fec1043e39d4f18874a5f217742374c3b7dd..e6a63c02699d575ed7f5a3852dc3e20eacee0db1 100644
--- a/src/backend/utils/init/postinit.c
+++ b/src/backend/utils/init/postinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.192 2009/07/08 17:53:29 heikki Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.193 2009/07/31 20:26:23 tgl Exp $
  *
  *
  *-------------------------------------------------------------------------
@@ -39,6 +39,7 @@
 #include "storage/lmgr.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
+#include "storage/procsignal.h"
 #include "storage/sinvaladt.h"
 #include "storage/smgr.h"
 #include "utils/acl.h"
@@ -451,6 +452,9 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username,
 	if (MyBackendId > MaxBackends || MyBackendId <= 0)
 		elog(FATAL, "bad backend id: %d", MyBackendId);
 
+	/* Now that we have a BackendId, we can participate in ProcSignal */
+	ProcSignalInit(MyBackendId);
+
 	/*
 	 * bufmgr needs another initialization call too
 	 */
diff --git a/src/include/bootstrap/bootstrap.h b/src/include/bootstrap/bootstrap.h
index ab549eabb1f18f934cc3918ddc4e79099d096946..acc6468f9da50ff6e492b2dfc929a57b051bb21a 100644
--- a/src/include/bootstrap/bootstrap.h
+++ b/src/include/bootstrap/bootstrap.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.51 2009/01/01 17:23:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/bootstrap/bootstrap.h,v 1.52 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,7 +70,9 @@ typedef enum
 	BootstrapProcess,
 	StartupProcess,
 	BgWriterProcess,
-	WalWriterProcess
+	WalWriterProcess,
+
+	NUM_AUXPROCTYPES			/* Must be last! */
 } AuxProcType;
 
 #endif   /* BOOTSTRAP_H */
diff --git a/src/include/commands/async.h b/src/include/commands/async.h
index 789a8d9c793588eb59c841121920a1a6c7f385bc..5ee10f583c03944ee770b6f55e991e5afb14cf4c 100644
--- a/src/include/commands/async.h
+++ b/src/include/commands/async.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/async.h,v 1.37 2009/01/01 17:23:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/async.h,v 1.38 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -29,8 +29,8 @@ extern void AtSubCommit_Notify(void);
 extern void AtSubAbort_Notify(void);
 extern void AtPrepare_Notify(void);
 
-/* signal handler for inbound notifies (SIGUSR2) */
-extern void NotifyInterruptHandler(SIGNAL_ARGS);
+/* signal handler for inbound notifies (PROCSIG_NOTIFY_INTERRUPT) */
+extern void HandleNotifyInterrupt(void);
 
 /*
  * enable/disable processing of inbound notifies directly from signal handler.
diff --git a/src/include/storage/procsignal.h b/src/include/storage/procsignal.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f493ac77ff13bea18e222ae2d1c3d81c93f0b8d
--- /dev/null
+++ b/src/include/storage/procsignal.h
@@ -0,0 +1,50 @@
+/*-------------------------------------------------------------------------
+ *
+ * procsignal.h
+ *	  Routines for interprocess signalling
+ *
+ *
+ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/storage/procsignal.h,v 1.1 2009/07/31 20:26:23 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PROCSIGNAL_H
+#define PROCSIGNAL_H
+
+#include "storage/backendid.h"
+
+
+/*
+ * Reasons for signalling a Postgres child process (a backend or an auxiliary
+ * process, like bgwriter).  We can cope with concurrent signals for different
+ * reasons.  However, if the same reason is signaled multiple times in quick
+ * succession, the process is likely to observe only one notification of it.
+ * This is okay for the present uses.
+ *
+ * Also, because of race conditions, it's important that all the signals be
+ * defined so that no harm is done if a process mistakenly receives one.
+ */
+typedef enum
+{
+	PROCSIG_CATCHUP_INTERRUPT,	/* sinval catchup interrupt */
+	PROCSIG_NOTIFY_INTERRUPT,	/* listen/notify interrupt */
+
+	NUM_PROCSIGNALS				/* Must be last! */
+} ProcSignalReason;
+
+/*
+ * prototypes for functions in procsignal.c
+ */
+extern Size ProcSignalShmemSize(void);
+extern void ProcSignalShmemInit(void);
+
+extern void ProcSignalInit(int pss_idx);
+extern int  SendProcSignal(pid_t pid, ProcSignalReason reason,
+						   BackendId backendId);
+
+extern void procsignal_sigusr1_handler(SIGNAL_ARGS);
+
+#endif   /* PROCSIGNAL_H */
diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h
index f332ec285e22fb2671e8e91af31ba2f38d44b10f..84edb5b31e3a470f5482c75d36e232dd4250150e 100644
--- a/src/include/storage/sinval.h
+++ b/src/include/storage/sinval.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.52 2009/06/11 14:49:12 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.53 2009/07/31 20:26:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -89,8 +89,8 @@ extern void ReceiveSharedInvalidMessages(
 					  void (*invalFunction) (SharedInvalidationMessage *msg),
 							 void (*resetFunction) (void));
 
-/* signal handler for catchup events (SIGUSR1) */
-extern void CatchupInterruptHandler(SIGNAL_ARGS);
+/* signal handler for catchup events (PROCSIG_CATCHUP_INTERRUPT) */
+extern void HandleCatchupInterrupt(void);
 
 /*
  * enable/disable processing of catchup events directly from signal handler.