diff -rcN base/src/backend/bootstrap/bootstrap.c new/src/backend/bootstrap/bootstrap.c
*** base/src/backend/bootstrap/bootstrap.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/bootstrap/bootstrap.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 35,40 ****
--- 35,41 ----
  #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,393 ****
--- 389,404 ----
  		InitAuxiliaryProcess();
  #endif
  
+ 		/*
+ 		 * Assign the ProcSignalSlot to an auxiliary process. Since it doesn't
+ 		 * have backend ID, the slot which lies behind the ProcSignalSlot array
+ 		 * is statically allocated to it according to the process type (auxType).
+ 		 * Backends use the slot 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.
+  		 */
+ 		ProcSignalInit(MaxBackends + auxType + 1);
+ 
  		/* finish setting up bufmgr.c */
  		InitBufferPoolBackend();
  
diff -rcN base/src/backend/commands/async.c new/src/backend/commands/async.c
*** base/src/backend/commands/async.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/commands/async.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 35,48 ****
   *	  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).
   *	  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
   *	  processing to occur just before we next go idle.
   *
   * 5. Inbound-notify processing consists of scanning pg_listener for tuples
--- 35,49 ----
   *	  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
!  *	  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 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,100 ****
--- 96,102 ----
  #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,645 ****
  
  			/*
  			 * 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.
  			 */
! 			if (kill(listenerPID, SIGUSR2) < 0)
  			{
  				/*
  				 * Get rid of pg_listener entry if it refers to a PID that no
--- 636,648 ----
  
  			/*
  			 * If someone has already notified this listener, we don't bother
! 			 * modifying the table, but we do still send a PROCSIG_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.
  			 */
! 			if (SendProcSignal(listenerPID, PROCSIG_NOTIFY_INTERRUPT,
! 							   InvalidBackendId) < 0)
  			{
  				/*
  				 * Get rid of pg_listener entry if it refers to a PID that no
***************
*** 777,797 ****
  }
  
  /*
!  * NotifyInterruptHandler
   *
!  *		This is the signal handler for SIGUSR2.
   *
   *		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)
  {
- 	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.
--- 780,798 ----
  }
  
  /*
!  * HandleNotifyInterrupt
   *
!  *		This is called when PROCSIG_NOTIFY_INTERRUPT signal 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
! HandleNotifyInterrupt(void)
  {
  	/*
! 	 * 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.
***************
*** 815,821 ****
  
  		/*
  		 * I'm not sure whether some flavors of Unix might allow another
! 		 * SIGUSR2 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.
  		 */
--- 816,822 ----
  
  		/*
  		 * I'm not sure whether some flavors of Unix might allow another
! 		 * 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.
  		 */
***************
*** 854,861 ****
  		 */
  		notifyInterruptOccurred = 1;
  	}
- 
- 	errno = save_errno;
  }
  
  /*
--- 855,860 ----
***************
*** 922,929 ****
   *		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
   *		must return the previous state of the flag.
   */
  bool
--- 921,928 ----
   *		a frontend command.  Signal handler execution of inbound notifies
   *		is disabled until the next EnableNotifyInterrupt call.
   *
!  *		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,947 ****
   * 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.
   *		Scan pg_listener for arriving notifies, report them to my front end,
   *		and clear the notification field in pg_listener until next time.
   *
--- 939,946 ----
   * ProcessIncomingNotify
   *
   *		Deal with arriving NOTIFYs from other backends.
!  *		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,967 ****
  				nulls[Natts_pg_listener];
  	bool		catchup_enabled;
  
! 	/* Must prevent SIGUSR1 interrupt while I am running */
  	catchup_enabled = DisableCatchupInterrupt();
  
  	if (Trace_notify)
--- 960,966 ----
  				nulls[Natts_pg_listener];
  	bool		catchup_enabled;
  
! 	/* Must prevent catchup interrupt while I am running */
  	catchup_enabled = DisableCatchupInterrupt();
  
  	if (Trace_notify)
diff -rcN base/src/backend/postmaster/autovacuum.c new/src/backend/postmaster/autovacuum.c
*** base/src/backend/postmaster/autovacuum.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/postmaster/autovacuum.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 91,96 ****
--- 91,97 ----
  #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"
***************
*** 1501,1507 ****
  	pqsignal(SIGALRM, handle_sig_alarm);
  
  	pqsignal(SIGPIPE, SIG_IGN);
! 	pqsignal(SIGUSR1, CatchupInterruptHandler);
  	/* We don't listen for async notifies */
  	pqsignal(SIGUSR2, SIG_IGN);
  	pqsignal(SIGFPE, FloatExceptionHandler);
--- 1502,1508 ----
  	pqsignal(SIGALRM, handle_sig_alarm);
  
  	pqsignal(SIGPIPE, SIG_IGN);
! 	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
  	/* We don't listen for async notifies */
  	pqsignal(SIGUSR2, SIG_IGN);
  	pqsignal(SIGFPE, FloatExceptionHandler);
diff -rcN base/src/backend/storage/ipc/Makefile new/src/backend/storage/ipc/Makefile
*** base/src/backend/storage/ipc/Makefile	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/storage/ipc/Makefile	2009-07-29 18:35:46.000000000 +0900
***************
*** 15,21 ****
  endif
  endif
  
! OBJS = ipc.o ipci.o pmsignal.o procarray.o shmem.o shmqueue.o \
  	sinval.o sinvaladt.o
  
  include $(top_srcdir)/src/backend/common.mk
--- 15,21 ----
  endif
  endif
  
! 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 -rcN base/src/backend/storage/ipc/ipci.c new/src/backend/storage/ipc/ipci.c
*** base/src/backend/storage/ipc/ipci.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/storage/ipc/ipci.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 30,35 ****
--- 30,36 ----
  #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"
  
***************
*** 114,119 ****
--- 115,121 ----
  		size = add_size(size, PMSignalShmemSize());
  		size = add_size(size, BgWriterShmemSize());
  		size = add_size(size, AutoVacuumShmemSize());
+ 		size = add_size(size, ProcSignalShmemSize());
  		size = add_size(size, BTreeShmemSize());
  		size = add_size(size, SyncScanShmemSize());
  #ifdef EXEC_BACKEND
***************
*** 210,215 ****
--- 212,218 ----
  	PMSignalShmemInit();
  	BgWriterShmemInit();
  	AutoVacuumShmemInit();
+ 	ProcSignalShmemInit();
  
  	/*
  	 * Set up other modules that need some shared memory space
diff -rcN base/src/backend/storage/ipc/procsignal.c new/src/backend/storage/ipc/procsignal.c
*** base/src/backend/storage/ipc/procsignal.c	1970-01-01 09:00:00.000000000 +0900
--- new/src/backend/storage/ipc/procsignal.c	2009-07-29 18:45:25.000000000 +0900
***************
*** 0 ****
--- 1,248 ----
+ /*-------------------------------------------------------------------------
+  *
+  * procsignal.c
+  *	  routines for signaling processes
+  *
+  *
+  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * IDENTIFICATION
+  *	  $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ #include "postgres.h"
+ 
+ #include <signal.h>
+ #include <unistd.h>
+ 
+ #include "bootstrap/bootstrap.h"
+ #include "commands/async.h"
+ #include "miscadmin.h"
+ #include "storage/backendid.h"
+ #include "storage/ipc.h"
+ #include "storage/procsignal.h"
+ #include "storage/shmem.h"
+ #include "storage/sinval.h"
+ 
+ /*
+  * SIGUSR1 signal is multiplexed for multiple events. 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 process will 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 signaling.
+  * 
+  * 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;
+ 
+ static ProcSignalSlot *ProcSignalSlots;
+ 
+ static bool CheckProcSignal(ProcSignalReason reason);
+ static void CleanupProcSignalState(int status, Datum arg);
+ 
+ /*
+  * ProcSignalShmemInit - initialize during shared-memory creation
+  */
+ Size
+ ProcSignalShmemSize(void)
+ {
+ 	return (MaxBackends + NUM_AUXPROCTYPE) * sizeof(ProcSignalSlot);
+ }
+ 
+ /*
+  * ProcSignalShmemInit - initialize during shared-memory creation
+  */
+ void
+ ProcSignalShmemInit(void)
+ {
+ 	bool		found;
+ 
+ 	ProcSignalSlots = (ProcSignalSlot *)
+ 		ShmemInitStruct("ProcSignalSlots", ProcSignalShmemSize(),
+ 						&found);
+ 
+ 	if (!found)
+ 		MemSet(ProcSignalSlots, 0, ProcSignalShmemSize());
+ }
+ 
+ /*
+  * ProcSignalInit - register a process to the procsignal array
+  */
+ void
+ ProcSignalInit(int pss_idx)
+ {
+ 	volatile ProcSignalSlot *slot;
+ 
+ 	Assert(pss_idx >= 1 &&
+ 		   pss_idx <= MaxBackends + NUM_AUXPROCTYPE);
+ 
+ 	slot = &ProcSignalSlots[pss_idx - 1];
+ 	MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t));
+ 	slot->pss_pid = MyProcPid;
+ 
+ 	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];
+ 
+ 	/* 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(WARNING, "current process not in ProcSignalSlots array");
+ 		return;
+ 	}
+ 	slot->pss_pid = 0;
+ }
+ 
+ /*
+  * SendProcSignal - signal a process with a reason code
+  *
+  * Providing backendId is optional, but it will speed up the operation.
+  *
+  * On success (at least one signal was sent), zero is returned. On error,
+  * -1 is returned.
+  *
+  * 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
+ 	{
+ 		/*
+ 		 * Same as above, but linear search the array using pid. Search the
+ 		 * array back to front so as to reduce the search overhead. Passing
+ 		 * InvalidBackendId means that the target is most likely an auxiliary
+ 		 * process. Its slot lies behind the array, so the backward search
+ 		 * is efficient here.
+ 		 */
+ 		int i;
+ 		for (i = MaxBackends + NUM_AUXPROCTYPE - 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);
+ 			}
+ 		}
+ 	}
+ 
+ 	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;
+ 
+ 	if (MyBackendId != InvalidBackendId)
+ 	{
+ 		slot = &ProcSignalSlots[MyBackendId - 1];
+ 
+ 		/* 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;
+ 		}
+ 	}
+ 	else
+ 	{
+ 		int i;
+ 		for (i = MaxBackends + NUM_AUXPROCTYPE - 1; i >= 0; i--)
+ 		{
+ 			slot = &ProcSignalSlots[i];
+ 			if (slot->pss_pid == MyProcPid)
+ 			{
+ 				/* 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;
+ 				}
+ 
+ 				break;
+ 			}
+ 		}
+ 	}
+ 
+ 	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 -rcN base/src/backend/storage/ipc/sinval.c new/src/backend/storage/ipc/sinval.c
*** base/src/backend/storage/ipc/sinval.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/storage/ipc/sinval.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 26,33 ****
   * 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.
   *
   * State for catchup events consists of two flags: one saying whether
   * the signal handler is currently allowed to call ProcessCatchupEvent
--- 26,33 ----
   * 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
!  * PROCSIG_CATHCUP_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,153 ****
  
  
  /*
!  * CatchupInterruptHandler
   *
!  * This is the signal handler for SIGUSR1.
   *
   * If we are idle (catchupInterruptEnabled is set), we can safely
   * invoke ProcessCatchupEvent directly.  Otherwise, just set a flag
--- 145,153 ----
  
  
  /*
!  * HandleCatchupInterrupt
   *
!  * This is called when PROCSIG_CATCHUP_INTERRUPT signal is received.
   *
   * If we are idle (catchupInterruptEnabled is set), we can safely
   * invoke ProcessCatchupEvent directly.  Otherwise, just set a flag
***************
*** 157,169 ****
   * since there's no longer any reason to do anything.)
   */
  void
! CatchupInterruptHandler(SIGNAL_ARGS)
  {
- 	int			save_errno = errno;
- 
  	/*
! 	 * Note: this is a SIGNAL HANDLER.	You must be very wary what you do
! 	 * here.
  	 */
  
  	/* Don't joggle the elbow of proc_exit */
--- 157,167 ----
   * since there's no longer any reason to do anything.)
   */
  void
! HandleCatchupInterrupt(void)
  {
  	/*
! 	 * 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,224 ****
  		 */
  		catchupInterruptOccurred = 1;
  	}
- 
- 	errno = save_errno;
  }
  
  /*
--- 215,220 ----
***************
*** 273,280 ****
   * 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
   * must return the previous state of the flag.
   */
  bool
--- 269,276 ----
   * a frontend command.	Signal handler execution of catchup events
   * is disabled until the next EnableCatchupInterrupt call.
   *
!  * 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,307 ****
  /*
   * ProcessCatchupEvent
   *
!  * Respond to a catchup event (SIGUSR1) 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).
   */
  static void
  ProcessCatchupEvent(void)
  {
  	bool		notify_enabled;
  
! 	/* Must prevent SIGUSR2 interrupt while I am running */
  	notify_enabled = DisableNotifyInterrupt();
  
  	/*
--- 286,304 ----
  /*
   * ProcessCatchupEvent
   *
!  * Respond to a catchup event (PROCSIG_CATCHUP_INTERRUPT) from another
!  * backend.
   *
!  * 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 notify interrupt while I am running */
  	notify_enabled = DisableNotifyInterrupt();
  
  	/*
diff -rcN base/src/backend/storage/ipc/sinvaladt.c new/src/backend/storage/ipc/sinvaladt.c
*** base/src/backend/storage/ipc/sinvaladt.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/storage/ipc/sinvaladt.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 21,26 ****
--- 21,27 ----
  #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"
***************
*** 138,143 ****
--- 139,145 ----
  {
  	/* procPid is zero in an inactive ProcState array entry. */
  	pid_t		procPid;		/* PID of backend, for signaling */
+ 	BackendId	backendId;		/* backend ID, for signaling */
  	/* nextMsgNum is meaningless if procPid == 0 or resetState is true. */
  	int			nextMsgNum;		/* next message number to read */
  	bool		resetState;		/* backend needs to reset its state */
***************
*** 236,241 ****
--- 238,244 ----
  	for (i = 0; i < shmInvalBuffer->maxBackends; i++)
  	{
  		shmInvalBuffer->procState[i].procPid = 0;		/* inactive */
+ 		shmInvalBuffer->procState[i].backendId = InvalidBackendId;
  		shmInvalBuffer->procState[i].nextMsgNum = 0;	/* meaningless */
  		shmInvalBuffer->procState[i].resetState = false;
  		shmInvalBuffer->procState[i].signaled = false;
***************
*** 304,309 ****
--- 307,313 ----
  
  	/* mark myself active, with all extant messages already read */
  	stateP->procPid = MyProcPid;
+ 	stateP->backendId = MyBackendId;
  	stateP->nextMsgNum = segP->maxMsgNum;
  	stateP->resetState = false;
  	stateP->signaled = false;
***************
*** 342,347 ****
--- 346,352 ----
  
  	/* Mark myself inactive */
  	stateP->procPid = 0;
+ 	stateP->backendId = InvalidBackendId;
  	stateP->nextMsgNum = 0;
  	stateP->resetState = false;
  	stateP->signaled = false;
***************
*** 644,661 ****
  		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.
  	 */
  	if (needSig)
  	{
! 		pid_t		his_pid = needSig->procPid;
  
  		needSig->signaled = true;
  		LWLockRelease(SInvalReadLock);
  		LWLockRelease(SInvalWriteLock);
  		elog(DEBUG4, "sending sinval catchup signal to PID %d", (int) his_pid);
! 		kill(his_pid, SIGUSR1);
  		if (callerHasWriteLock)
  			LWLockAcquire(SInvalWriteLock, LW_EXCLUSIVE);
  	}
--- 649,668 ----
  		segP->nextThreshold = (numMsgs / CLEANUP_QUANTUM + 1) * CLEANUP_QUANTUM;
  
  	/*
! 	 * 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->backendId;
  
  		needSig->signaled = true;
  		LWLockRelease(SInvalReadLock);
  		LWLockRelease(SInvalWriteLock);
  		elog(DEBUG4, "sending sinval catchup signal to PID %d", (int) his_pid);
! 		SendProcSignal(his_pid, PROCSIG_CATCHUP_INTERRUPT, his_backendId);
  		if (callerHasWriteLock)
  			LWLockAcquire(SInvalWriteLock, LW_EXCLUSIVE);
  	}
diff -rcN base/src/backend/tcop/postgres.c new/src/backend/tcop/postgres.c
*** base/src/backend/tcop/postgres.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/tcop/postgres.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 59,64 ****
--- 59,65 ----
  #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,3228 ****
  	 * of output during who-knows-what operation...
  	 */
  	pqsignal(SIGPIPE, SIG_IGN);
! 	pqsignal(SIGUSR1, CatchupInterruptHandler);
! 	pqsignal(SIGUSR2, NotifyInterruptHandler);
  	pqsignal(SIGFPE, FloatExceptionHandler);
  
  	/*
--- 3222,3229 ----
  	 * of output during who-knows-what operation...
  	 */
  	pqsignal(SIGPIPE, SIG_IGN);
! 	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
! 	pqsignal(SIGUSR2, SIG_IGN);
  	pqsignal(SIGFPE, FloatExceptionHandler);
  
  	/*
diff -rcN base/src/backend/utils/init/postinit.c new/src/backend/utils/init/postinit.c
*** base/src/backend/utils/init/postinit.c	2009-07-29 18:35:42.000000000 +0900
--- new/src/backend/utils/init/postinit.c	2009-07-29 18:35:46.000000000 +0900
***************
*** 39,44 ****
--- 39,45 ----
  #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,456 ****
--- 452,459 ----
  	if (MyBackendId > MaxBackends || MyBackendId <= 0)
  		elog(FATAL, "bad backend id: %d", MyBackendId);
  
+ 	ProcSignalInit(MyBackendId);
+ 
  	/*
  	 * bufmgr needs another initialization call too
  	 */
diff -rcN base/src/include/bootstrap/bootstrap.h new/src/include/bootstrap/bootstrap.h
*** base/src/include/bootstrap/bootstrap.h	2009-07-29 18:35:42.000000000 +0900
--- new/src/include/bootstrap/bootstrap.h	2009-07-29 18:35:46.000000000 +0900
***************
*** 70,76 ****
  	BootstrapProcess,
  	StartupProcess,
  	BgWriterProcess,
! 	WalWriterProcess
  } AuxProcType;
  
  #endif   /* BOOTSTRAP_H */
--- 70,78 ----
  	BootstrapProcess,
  	StartupProcess,
  	BgWriterProcess,
! 	WalWriterProcess,
! 
! 	NUM_AUXPROCTYPE
  } AuxProcType;
  
  #endif   /* BOOTSTRAP_H */
diff -rcN base/src/include/commands/async.h new/src/include/commands/async.h
*** base/src/include/commands/async.h	2009-07-29 18:35:42.000000000 +0900
--- new/src/include/commands/async.h	2009-07-29 18:35:46.000000000 +0900
***************
*** 29,36 ****
  extern void AtSubAbort_Notify(void);
  extern void AtPrepare_Notify(void);
  
! /* signal handler for inbound notifies (SIGUSR2) */
! extern void NotifyInterruptHandler(SIGNAL_ARGS);
  
  /*
   * enable/disable processing of inbound notifies directly from signal handler.
--- 29,36 ----
  extern void AtSubAbort_Notify(void);
  extern void AtPrepare_Notify(void);
  
! /* signal handler for inbound notifies (PROCSIG_NOTIFY_INTERRUPT) */
! extern void HandleNotifyInterrupt(void);
  
  /*
   * enable/disable processing of inbound notifies directly from signal handler.
diff -rcN base/src/include/storage/procsignal.h new/src/include/storage/procsignal.h
*** base/src/include/storage/procsignal.h	1970-01-01 09:00:00.000000000 +0900
--- new/src/include/storage/procsignal.h	2009-07-29 18:35:46.000000000 +0900
***************
*** 0 ****
--- 1,45 ----
+ /*-------------------------------------------------------------------------
+  *
+  * procsignal.h
+  *	  routines for signaling processes XXX
+  *
+  *
+  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * $PostgreSQL$
+  *
+  *-------------------------------------------------------------------------
+  */
+ #ifndef PROCSIGNAL_H
+ #define PROCSIGNAL_H
+ 
+ #include "storage/backendid.h"
+ 
+ 
+ /*
+  * Reasons for signaling a process (a backend or an auxiliary process, like
+  * autovacuum worker). We can cope with simultaneous signals for different
+  * reasons. If the same reason is signaled multiple times in quick succession,
+  * however, the process is likely to observe only one notification of it.
+  * This is okay for the present uses.
+  */
+ typedef enum
+ {
+        PROCSIG_CATCHUP_INTERRUPT,      /* catchup interrupt */
+ 	   PROCSIG_NOTIFY_INTERRUPT,       /* notify interrupt */
+        NUM_PROCSIGNALS                         /* Must be last value of enum! */
+ } 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 -rcN base/src/include/storage/sinval.h new/src/include/storage/sinval.h
*** base/src/include/storage/sinval.h	2009-07-29 18:35:42.000000000 +0900
--- new/src/include/storage/sinval.h	2009-07-29 18:35:46.000000000 +0900
***************
*** 89,96 ****
  					  void (*invalFunction) (SharedInvalidationMessage *msg),
  							 void (*resetFunction) (void));
  
! /* signal handler for catchup events (SIGUSR1) */
! extern void CatchupInterruptHandler(SIGNAL_ARGS);
  
  /*
   * enable/disable processing of catchup events directly from signal handler.
--- 89,96 ----
  					  void (*invalFunction) (SharedInvalidationMessage *msg),
  							 void (*resetFunction) (void));
  
! /* signal handler for catchup events (PROCSIG_CATCHUP_INTERRUPT) */
! extern void HandleCatchupInterrupt(void);
  
  /*
   * enable/disable processing of catchup events directly from signal handler.