diff -rcN base/src/backend/bootstrap/bootstrap.c new/src/backend/bootstrap/bootstrap.c
*** base/src/backend/bootstrap/bootstrap.c	2009-07-17 21:32:03.000000000 +0900
--- new/src/backend/bootstrap/bootstrap.c	2009-07-17 21:48:33.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,397 ----
  		InitAuxiliaryProcess();
  #endif
  
+ 		/* register a process to the procsignal array */
+ 		ProcSignalInit();
+ 
  		/* finish setting up bufmgr.c */
  		InitBufferPoolBackend();
  
diff -rcN base/src/backend/postmaster/autovacuum.c new/src/backend/postmaster/autovacuum.c
*** base/src/backend/postmaster/autovacuum.c	2009-07-17 21:32:03.000000000 +0900
--- new/src/backend/postmaster/autovacuum.c	2009-07-17 21:32:08.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-17 21:32:03.000000000 +0900
--- new/src/backend/storage/ipc/Makefile	2009-07-17 21:32:08.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-17 21:32:03.000000000 +0900
--- new/src/backend/storage/ipc/ipci.c	2009-07-17 21:32:08.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-17 22:28:08.000000000 +0900
***************
*** 0 ****
--- 1,233 ----
+ /*-------------------------------------------------------------------------
+  *
+  * procsignal.c
+  *	  routines for signaling processes
+  *
+  *
+  * Portions Copyright (c) 1996-2008, 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 "miscadmin.h"
+ #include "storage/backendid.h"
+ #include "storage/ipc.h"
+ #include "storage/proc.h"
+ #include "storage/procsignal.h"
+ #include "storage/shmem.h"
+ #include "storage/sinval.h"
+ #include "storage/spin.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];
+ 
+ 	/* protects shared variables shown above */
+ 	slock_t		pss_lck;
+ } 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_AUXILIARY_PROCS) * sizeof(ProcSignalSlot);
+ }
+ 
+ 
+ /*
+  * ProcSignalShmemInit - initialize during shared-memory creation
+  */
+ void
+ ProcSignalShmemInit(void)
+ {
+ 	bool		found;
+ 	int			i;
+ 
+ 	ProcSignalSlots = (ProcSignalSlot *)
+ 		ShmemInitStruct("ProcSignalSlots", ProcSignalShmemSize(),
+ 						&found);
+ 
+ 	if (found)
+ 		return;
+ 
+ 	MemSet(ProcSignalSlots, 0, ProcSignalShmemSize());
+ 	for (i = 0; i < MaxBackends + NUM_AUXILIARY_PROCS; i++)
+ 	{
+ 		volatile ProcSignalSlot *slot;
+ 
+ 		slot = &ProcSignalSlots[i];
+ 		SpinLockInit(&slot->pss_lck);
+ 	}
+ }
+ 
+ /*
+  * ProcSignalInit - register a process to the procsignal array
+  */
+ void
+ ProcSignalInit(void)
+ {
+ 	volatile ProcSignalSlot *slot;
+ 
+ 	Assert(MyBackendId >= 1 &&
+ 		   MyBackendId <= MaxBackends + NUM_AUXILIARY_PROCS);
+ 
+ 	slot = &ProcSignalSlots[MyBackendId - 1];
+ 	SpinLockAcquire(&slot->pss_lck);
+ 	MemSet(slot->pss_signalFlags, 0, NUM_PROCSIGNALS * sizeof(sig_atomic_t));
+ 	SpinLockRelease(&slot->pss_lck);
+ 	slot->pss_pid = MyProcPid;
+ 
+ 	on_shmem_exit(CleanupProcSignalState, Int32GetDatum(MyBackendId));
+ }
+ 
+ 
+ /*
+  * CleanupProcSignalState
+  *		Remove current process from ProcSignalSlots
+  *
+  * This function is called via on_shmem_exit() during backend shutdown.
+  *
+  * arg is really of type "BackendId".
+  */
+ static void
+ CleanupProcSignalState(int status, Datum arg)
+ {
+ 	BackendId	backendId = (BackendId) DatumGetInt32(arg);
+ 	volatile ProcSignalSlot *slot;
+ 	
+ 	slot = &ProcSignalSlots[backendId - 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.
+  *
+  * Not to be confused with ProcSendSignal
+  */
+ void
+ SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
+ {
+ 	volatile ProcSignalSlot *slot;
+ 
+ 	if (backendId != InvalidBackendId)
+ 	{
+ 		slot = &ProcSignalSlots[backendId - 1];
+ 
+ 		SpinLockAcquire(&slot->pss_lck);
+ 		if (slot->pss_pid == pid)
+ 		{
+ 			/* Atomically set the proper flag */
+ 			slot->pss_signalFlags[reason] = true;
+ 			SpinLockRelease(&slot->pss_lck);
+ 
+ 			/* Send signal */
+ 			kill(pid, SIGUSR1);
+ 		}
+ 		else
+ 			SpinLockRelease(&slot->pss_lck);
+ 	}
+ 	else
+ 	{
+ 		/* same as above, but linear search the array using pid */
+ 		int i;
+ 		for (i = 0; i < MaxBackends + NUM_AUXILIARY_PROCS; i++)
+ 		{
+ 			slot = &ProcSignalSlots[i];
+ 
+ 			SpinLockAcquire(&slot->pss_lck);
+ 			if (slot->pss_pid == pid)
+ 			{
+ 				/* Atomically set the proper flag */
+ 				slot->pss_signalFlags[reason] = true;
+ 				SpinLockRelease(&slot->pss_lck);
+ 
+ 				/* Send signal */
+ 				kill(pid, SIGUSR1);
+ 
+ 				break;
+ 			}
+ 			SpinLockRelease(&slot->pss_lck);
+ 		}
+ 	}
+ }
+ 
+ /*
+  * 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;
+ 
+ 	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;
+ 	}
+ 	return false;
+ }
+ 
+ /*
+  * procsignal_sigusr1_handler - handle SIGUSR1 signal.
+  */
+ void
+ procsignal_sigusr1_handler(SIGNAL_ARGS)
+ {
+ 	int		save_errno = errno;
+ 
+ 	if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
+ 		HandleCatchupInterrupt();
+ 
+ 	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-17 21:32:03.000000000 +0900
--- new/src/backend/storage/ipc/sinval.c	2009-07-17 21:32:08.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 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 ----
***************
*** 290,296 ****
  /*
   * 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
--- 286,293 ----
  /*
   * ProcessCatchupEvent
   *
!  * 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
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-17 21:32:03.000000000 +0900
--- new/src/backend/storage/ipc/sinvaladt.c	2009-07-17 21:32:08.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/storage/lmgr/proc.c new/src/backend/storage/lmgr/proc.c
*** base/src/backend/storage/lmgr/proc.c	2009-07-17 21:32:03.000000000 +0900
--- new/src/backend/storage/lmgr/proc.c	2009-07-17 21:46:58.000000000 +0900
***************
*** 425,430 ****
--- 425,438 ----
  	SpinLockRelease(ProcStructLock);
  
  	/*
+ 	 * Assign backend ID to auxiliary processes like backends, in order to
+ 	 * allow multiplexing signal to auxiliary processes. Since backends use
+ 	 * ID in the range from 1 to MaxBackends (inclusive), we assign
+ 	 * auxiliary processes with MaxBackends + proctype + 1 as an unique ID.
+ 	 */
+ 	MyBackendId = MaxBackends + proctype + 1;
+ 
+ 	/*
  	 * Initialize all fields of MyProc, except for the semaphore which was
  	 * prepared for us by InitProcGlobal.
  	 */
***************
*** 433,439 ****
  	MyProc->lxid = InvalidLocalTransactionId;
  	MyProc->xid = InvalidTransactionId;
  	MyProc->xmin = InvalidTransactionId;
! 	MyProc->backendId = InvalidBackendId;
  	MyProc->databaseId = InvalidOid;
  	MyProc->roleId = InvalidOid;
  	MyProc->inCommit = false;
--- 441,447 ----
  	MyProc->lxid = InvalidLocalTransactionId;
  	MyProc->xid = InvalidTransactionId;
  	MyProc->xmin = InvalidTransactionId;
! 	MyProc->backendId = MyBackendId;
  	MyProc->databaseId = InvalidOid;
  	MyProc->roleId = InvalidOid;
  	MyProc->inCommit = false;
diff -rcN base/src/backend/tcop/postgres.c new/src/backend/tcop/postgres.c
*** base/src/backend/tcop/postgres.c	2009-07-17 21:32:03.000000000 +0900
--- new/src/backend/tcop/postgres.c	2009-07-17 21:32:08.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,3227 ****
  	 * of output during who-knows-what operation...
  	 */
  	pqsignal(SIGPIPE, SIG_IGN);
! 	pqsignal(SIGUSR1, CatchupInterruptHandler);
  	pqsignal(SIGUSR2, NotifyInterruptHandler);
  	pqsignal(SIGFPE, FloatExceptionHandler);
  
--- 3222,3228 ----
  	 * of output during who-knows-what operation...
  	 */
  	pqsignal(SIGPIPE, SIG_IGN);
! 	pqsignal(SIGUSR1, procsignal_sigusr1_handler);
  	pqsignal(SIGUSR2, NotifyInterruptHandler);
  	pqsignal(SIGFPE, FloatExceptionHandler);
  
diff -rcN base/src/backend/utils/error/elog.c new/src/backend/utils/error/elog.c
*** base/src/backend/utils/error/elog.c	2009-07-17 21:32:03.000000000 +0900
--- new/src/backend/utils/error/elog.c	2009-07-17 21:32:08.000000000 +0900
***************
*** 1807,1813 ****
  				break;
  			case 'v':
  				/* keep VXID format in sync with lockfuncs.c */
! 				if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
  					appendStringInfo(buf, "%d/%u",
  									 MyProc->backendId, MyProc->lxid);
  				break;
--- 1807,1814 ----
  				break;
  			case 'v':
  				/* keep VXID format in sync with lockfuncs.c */
! 				if (MyProc != NULL && 
! 					MyProc->backendId >= 1 && MyProc->backendId <= MaxBackends)
  					appendStringInfo(buf, "%d/%u",
  									 MyProc->backendId, MyProc->lxid);
  				break;
***************
*** 1955,1961 ****
  
  	/* Virtual transaction id */
  	/* keep VXID format in sync with lockfuncs.c */
! 	if (MyProc != NULL && MyProc->backendId != InvalidBackendId)
  		appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid);
  	appendStringInfoChar(&buf, ',');
  
--- 1956,1963 ----
  
  	/* Virtual transaction id */
  	/* keep VXID format in sync with lockfuncs.c */
! 	if (MyProc != NULL &&
! 		MyProc->backendId >= 1 && MyProc->backendId <= MaxBackends)
  		appendStringInfo(&buf, "%d/%u", MyProc->backendId, MyProc->lxid);
  	appendStringInfoChar(&buf, ',');
  
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-17 21:32:03.000000000 +0900
--- new/src/backend/utils/init/postinit.c	2009-07-17 21:32:08.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();
+ 
  	/*
  	 * bufmgr needs another initialization call too
  	 */
diff -rcN base/src/include/storage/lock.h new/src/include/storage/lock.h
*** base/src/include/storage/lock.h	2009-07-17 21:32:03.000000000 +0900
--- new/src/include/storage/lock.h	2009-07-17 21:32:08.000000000 +0900
***************
*** 65,71 ****
  #define InvalidLocalTransactionId		0
  #define LocalTransactionIdIsValid(lxid) ((lxid) != InvalidLocalTransactionId)
  #define VirtualTransactionIdIsValid(vxid) \
! 	(((vxid).backendId != InvalidBackendId) && \
  	 LocalTransactionIdIsValid((vxid).localTransactionId))
  #define VirtualTransactionIdEquals(vxid1, vxid2) \
  	((vxid1).backendId == (vxid2).backendId && \
--- 65,72 ----
  #define InvalidLocalTransactionId		0
  #define LocalTransactionIdIsValid(lxid) ((lxid) != InvalidLocalTransactionId)
  #define VirtualTransactionIdIsValid(vxid) \
! 	(((vxid).backendId >  InvalidBackendId) && \
! 	 ((vxid).backendId <= MaxBackends) && \
  	 LocalTransactionIdIsValid((vxid).localTransactionId))
  #define VirtualTransactionIdEquals(vxid1, vxid2) \
  	((vxid1).backendId == (vxid2).backendId && \
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-17 21:32:08.000000000 +0900
***************
*** 0 ****
--- 1,44 ----
+ /*-------------------------------------------------------------------------
+  *
+  * 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 */
+        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(void);
+ extern void 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-17 21:32:03.000000000 +0900
--- new/src/include/storage/sinval.h	2009-07-17 21:32:08.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.