diff -dcrpN postgresql/src/backend/postmaster/autovacuum.c postgresql.1/src/backend/postmaster/autovacuum.c
*** postgresql/src/backend/postmaster/autovacuum.c	2012-05-11 09:23:17.033668629 +0200
--- postgresql.1/src/backend/postmaster/autovacuum.c	2012-05-11 09:32:17.075682608 +0200
***************
*** 86,94 ****
  #include "storage/ipc.h"
  #include "storage/latch.h"
  #include "storage/pmsignal.h"
- #include "storage/proc.h"
  #include "storage/procsignal.h"
  #include "storage/sinvaladt.h"
  #include "tcop/tcopprot.h"
  #include "utils/fmgroids.h"
  #include "utils/lsyscache.h"
--- 86,94 ----
  #include "storage/ipc.h"
  #include "storage/latch.h"
  #include "storage/pmsignal.h"
  #include "storage/procsignal.h"
  #include "storage/sinvaladt.h"
+ #include "storage/timeout.h"
  #include "tcop/tcopprot.h"
  #include "utils/fmgroids.h"
  #include "utils/lsyscache.h"
*************** AutoVacLauncherMain(int argc, char *argv
*** 484,490 ****
  
  		/* Forget any pending QueryCancel request */
  		QueryCancelPending = false;
! 		disable_sig_alarm(true);
  		QueryCancelPending = false;		/* again in case timeout occurred */
  
  		/* Report the error to the server log */
--- 484,490 ----
  
  		/* Forget any pending QueryCancel request */
  		QueryCancelPending = false;
! 		disable_all_timeouts(false);
  		QueryCancelPending = false;		/* again in case timeout occurred */
  
  		/* Report the error to the server log */
diff -dcrpN postgresql/src/backend/postmaster/postmaster.c postgresql.1/src/backend/postmaster/postmaster.c
*** postgresql/src/backend/postmaster/postmaster.c	2012-04-23 08:28:35.641057679 +0200
--- postgresql.1/src/backend/postmaster/postmaster.c	2012-05-11 09:32:17.079682630 +0200
***************
*** 112,118 ****
  #include "storage/ipc.h"
  #include "storage/pg_shmem.h"
  #include "storage/pmsignal.h"
! #include "storage/proc.h"
  #include "tcop/tcopprot.h"
  #include "utils/builtins.h"
  #include "utils/datetime.h"
--- 112,118 ----
  #include "storage/ipc.h"
  #include "storage/pg_shmem.h"
  #include "storage/pmsignal.h"
! #include "storage/timeout.h"
  #include "tcop/tcopprot.h"
  #include "utils/builtins.h"
  #include "utils/datetime.h"
*************** BackendInitialize(Port *port)
*** 3471,3479 ****
  	 * Ready to begin client interaction.  We will give up and exit(1) after a
  	 * time delay, so that a broken client can't hog a connection
  	 * indefinitely.  PreAuthDelay and any DNS interactions above don't count
! 	 * against the time limit.
  	 */
! 	if (!enable_sig_alarm(AuthenticationTimeout * 1000, false))
  		elog(FATAL, "could not set timer for startup packet timeout");
  
  	/*
--- 3471,3479 ----
  	 * Ready to begin client interaction.  We will give up and exit(1) after a
  	 * time delay, so that a broken client can't hog a connection
  	 * indefinitely.  PreAuthDelay and any DNS interactions above don't count
! 	 * against the time limit. Use the deadlock timeout interface.
  	 */
! 	if (!enable_timeout(DEADLOCK_TIMEOUT, AuthenticationTimeout * 1000))
  		elog(FATAL, "could not set timer for startup packet timeout");
  
  	/*
*************** BackendInitialize(Port *port)
*** 3511,3517 ****
  	/*
  	 * Disable the timeout, and prevent SIGTERM/SIGQUIT again.
  	 */
! 	if (!disable_sig_alarm(false))
  		elog(FATAL, "could not disable timer for startup packet timeout");
  	PG_SETMASK(&BlockSig);
  }
--- 3511,3517 ----
  	/*
  	 * Disable the timeout, and prevent SIGTERM/SIGQUIT again.
  	 */
! 	if (!disable_timeout(DEADLOCK_TIMEOUT, false))
  		elog(FATAL, "could not disable timer for startup packet timeout");
  	PG_SETMASK(&BlockSig);
  }
diff -dcrpN postgresql/src/backend/postmaster/startup.c postgresql.1/src/backend/postmaster/startup.c
*** postgresql/src/backend/postmaster/startup.c	2012-04-16 19:57:22.442915536 +0200
--- postgresql.1/src/backend/postmaster/startup.c	2012-05-11 09:32:17.080682636 +0200
***************
*** 27,33 ****
  #include "storage/ipc.h"
  #include "storage/latch.h"
  #include "storage/pmsignal.h"
! #include "storage/proc.h"
  #include "utils/guc.h"
  
  
--- 27,33 ----
  #include "storage/ipc.h"
  #include "storage/latch.h"
  #include "storage/pmsignal.h"
! #include "storage/timeout.h"
  #include "utils/guc.h"
  
  
*************** StartupProcessMain(void)
*** 195,202 ****
  	pqsignal(SIGTERM, StartupProcShutdownHandler);		/* request shutdown */
  	pqsignal(SIGQUIT, startupproc_quickdie);	/* hard crash time */
  	if (EnableHotStandby)
! 		pqsignal(SIGALRM, handle_standby_sig_alarm);	/* ignored unless
! 														 * InHotStandby */
  	else
  		pqsignal(SIGALRM, SIG_IGN);
  	pqsignal(SIGPIPE, SIG_IGN);
--- 195,202 ----
  	pqsignal(SIGTERM, StartupProcShutdownHandler);		/* request shutdown */
  	pqsignal(SIGQUIT, startupproc_quickdie);	/* hard crash time */
  	if (EnableHotStandby)
! 		pqsignal(SIGALRM, handle_sig_alarm);	/* ignored unless
! 								* InHotStandby */
  	else
  		pqsignal(SIGALRM, SIG_IGN);
  	pqsignal(SIGPIPE, SIG_IGN);
diff -dcrpN postgresql/src/backend/storage/ipc/standby.c postgresql.1/src/backend/storage/ipc/standby.c
*** postgresql/src/backend/storage/ipc/standby.c	2012-05-02 17:36:48.984503204 +0200
--- postgresql.1/src/backend/storage/ipc/standby.c	2012-05-11 09:32:17.124682881 +0200
***************
*** 23,32 ****
  #include "miscadmin.h"
  #include "storage/bufmgr.h"
  #include "storage/lmgr.h"
- #include "storage/proc.h"
  #include "storage/procarray.h"
  #include "storage/sinvaladt.h"
  #include "storage/standby.h"
  #include "utils/ps_status.h"
  #include "utils/timestamp.h"
  
--- 23,32 ----
  #include "miscadmin.h"
  #include "storage/bufmgr.h"
  #include "storage/lmgr.h"
  #include "storage/procarray.h"
  #include "storage/sinvaladt.h"
  #include "storage/standby.h"
+ #include "storage/timeout.h"
  #include "utils/ps_status.h"
  #include "utils/timestamp.h"
  
*************** ResolveRecoveryConflictWithLock(Oid dbOi
*** 394,400 ****
  void
  ResolveRecoveryConflictWithBufferPin(void)
  {
- 	bool		sig_alarm_enabled = false;
  	TimestampTz ltime;
  	TimestampTz now;
  
--- 394,399 ----
*************** ResolveRecoveryConflictWithBufferPin(voi
*** 409,417 ****
  		 * We're willing to wait forever for conflicts, so set timeout for
  		 * deadlock check (only)
  		 */
! 		if (enable_standby_sig_alarm(now, now, true))
! 			sig_alarm_enabled = true;
! 		else
  			elog(FATAL, "could not set timer for process wakeup");
  	}
  	else if (now >= ltime)
--- 408,414 ----
  		 * We're willing to wait forever for conflicts, so set timeout for
  		 * deadlock check (only)
  		 */
! 		if (!enable_timeout(STANDBY_DEADLOCK_TIMEOUT, DeadlockTimeout))
  			elog(FATAL, "could not set timer for process wakeup");
  	}
  	else if (now >= ltime)
*************** ResolveRecoveryConflictWithBufferPin(voi
*** 423,446 ****
  	}
  	else
  	{
  		/*
  		 * Wake up at ltime, and check for deadlocks as well if we will be
  		 * waiting longer than deadlock_timeout
  		 */
! 		if (enable_standby_sig_alarm(now, ltime, false))
! 			sig_alarm_enabled = true;
! 		else
  			elog(FATAL, "could not set timer for process wakeup");
  	}
  
  	/* Wait to be signaled by UnpinBuffer() */
  	ProcWaitForSignal();
  
! 	if (sig_alarm_enabled)
! 	{
! 		if (!disable_standby_sig_alarm())
! 			elog(FATAL, "could not disable timer for process wakeup");
! 	}
  }
  
  void
--- 420,447 ----
  	}
  	else
  	{
+ 		long		secs, msecs;
+ 		int		usecs;
+ 
  		/*
  		 * Wake up at ltime, and check for deadlocks as well if we will be
  		 * waiting longer than deadlock_timeout
  		 */
! 		if (!enable_timeout(STANDBY_DEADLOCK_TIMEOUT, DeadlockTimeout))
! 			elog(FATAL, "could not set timer for process wakeup");
! 
! 		TimestampDifference(now, ltime, &secs, &usecs);
! 		msecs = secs * 1000 + usecs / 1000;
! 
! 		if (!enable_timeout(STANDBY_TIMEOUT, msecs))
  			elog(FATAL, "could not set timer for process wakeup");
  	}
  
  	/* Wait to be signaled by UnpinBuffer() */
  	ProcWaitForSignal();
  
! 	if (!disable_all_timeouts(false))
! 		elog(FATAL, "could not disable timer for process wakeup");
  }
  
  void
diff -dcrpN postgresql/src/backend/storage/lmgr/Makefile postgresql.1/src/backend/storage/lmgr/Makefile
*** postgresql/src/backend/storage/lmgr/Makefile	2012-04-16 19:57:22.458915722 +0200
--- postgresql.1/src/backend/storage/lmgr/Makefile	2012-05-11 09:32:17.134682937 +0200
*************** subdir = src/backend/storage/lmgr
*** 12,18 ****
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = lmgr.o lock.o proc.o deadlock.o lwlock.o spin.o s_lock.o predicate.o
  
  include $(top_srcdir)/src/backend/common.mk
  
--- 12,18 ----
  top_builddir = ../../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = lmgr.o lock.o proc.o deadlock.o lwlock.o spin.o s_lock.o predicate.o timeout.o
  
  include $(top_srcdir)/src/backend/common.mk
  
diff -dcrpN postgresql/src/backend/storage/lmgr/proc.c postgresql.1/src/backend/storage/lmgr/proc.c
*** postgresql/src/backend/storage/lmgr/proc.c	2012-05-10 06:03:07.748716749 +0200
--- postgresql.1/src/backend/storage/lmgr/proc.c	2012-05-11 09:32:17.147683010 +0200
***************
*** 48,59 ****
  #include "storage/procarray.h"
  #include "storage/procsignal.h"
  #include "storage/spin.h"
  #include "utils/timestamp.h"
  
  
  /* GUC variables */
- int			DeadlockTimeout = 1000;
- int			StatementTimeout = 0;
  bool		log_lock_waits = false;
  
  /* Pointer to this process's PGPROC struct, if any */
--- 48,58 ----
  #include "storage/procarray.h"
  #include "storage/procsignal.h"
  #include "storage/spin.h"
+ #include "storage/timeout.h"
  #include "utils/timestamp.h"
  
  
  /* GUC variables */
  bool		log_lock_waits = false;
  
  /* Pointer to this process's PGPROC struct, if any */
*************** PGPROC *PreparedXactProcs = NULL;
*** 77,103 ****
  /* If we are waiting for a lock, this points to the associated LOCALLOCK */
  static LOCALLOCK *lockAwaited = NULL;
  
! /* Mark these volatile because they can be changed by signal handler */
! static volatile bool standby_timeout_active = false;
! static volatile bool statement_timeout_active = false;
! static volatile bool deadlock_timeout_active = false;
! static volatile DeadLockState deadlock_state = DS_NOT_YET_CHECKED;
! volatile bool cancel_from_timeout = false;
! 
! /* timeout_start_time is set when log_lock_waits is true */
! static TimestampTz timeout_start_time;
! 
! /* statement_fin_time is valid only if statement_timeout_active is true */
! static TimestampTz statement_fin_time;
! static TimestampTz statement_fin_time2; /* valid only in recovery */
! 
  
  static void RemoveProcFromArray(int code, Datum arg);
  static void ProcKill(int code, Datum arg);
  static void AuxiliaryProcKill(int code, Datum arg);
- static bool CheckStatementTimeout(void);
- static bool CheckStandbyTimeout(void);
- 
  
  /*
   * Report shared-memory space needed by InitProcGlobal.
--- 76,87 ----
  /* If we are waiting for a lock, this points to the associated LOCALLOCK */
  static LOCALLOCK *lockAwaited = NULL;
  
! /* Declared in timeout.c */
! extern volatile DeadLockState deadlock_state;
  
  static void RemoveProcFromArray(int code, Datum arg);
  static void ProcKill(int code, Datum arg);
  static void AuxiliaryProcKill(int code, Datum arg);
  
  /*
   * Report shared-memory space needed by InitProcGlobal.
*************** LockErrorCleanup(void)
*** 658,664 ****
  		return;
  
  	/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
! 	disable_sig_alarm(false);
  
  	/* Unlink myself from the wait queue, if on it (might not be anymore!) */
  	partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
--- 642,648 ----
  		return;
  
  	/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
! 	disable_timeout(DEADLOCK_TIMEOUT, false);
  
  	/* Unlink myself from the wait queue, if on it (might not be anymore!) */
  	partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1053,1059 ****
  	 * By delaying the check until we've waited for a bit, we can avoid
  	 * running the rather expensive deadlock-check code in most cases.
  	 */
! 	if (!enable_sig_alarm(DeadlockTimeout, false))
  		elog(FATAL, "could not set timer for process wakeup");
  
  	/*
--- 1037,1043 ----
  	 * By delaying the check until we've waited for a bit, we can avoid
  	 * running the rather expensive deadlock-check code in most cases.
  	 */
! 	if (!enable_timeout(DEADLOCK_TIMEOUT, DeadlockTimeout))
  		elog(FATAL, "could not set timer for process wakeup");
  
  	/*
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1143,1149 ****
  			DescribeLockTag(&buf, &locallock->tag.lock);
  			modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
  									   lockmode);
! 			TimestampDifference(timeout_start_time, GetCurrentTimestamp(),
  								&secs, &usecs);
  			msecs = secs * 1000 + usecs / 1000;
  			usecs = usecs % 1000;
--- 1127,1134 ----
  			DescribeLockTag(&buf, &locallock->tag.lock);
  			modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
  									   lockmode);
! 			TimestampDifference(get_timeout_start(DEADLOCK_TIMEOUT),
! 								GetCurrentTimestamp(),
  								&secs, &usecs);
  			msecs = secs * 1000 + usecs / 1000;
  			usecs = usecs % 1000;
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1205,1211 ****
  	/*
  	 * Disable the timer, if it's still running
  	 */
! 	if (!disable_sig_alarm(false))
  		elog(FATAL, "could not disable timer for process wakeup");
  
  	/*
--- 1190,1196 ----
  	/*
  	 * Disable the timer, if it's still running
  	 */
! 	if (!disable_timeout(DEADLOCK_TIMEOUT, false))
  		elog(FATAL, "could not disable timer for process wakeup");
  
  	/*
*************** ProcLockWakeup(LockMethod lockMethodTabl
*** 1337,1457 ****
  }
  
  /*
-  * CheckDeadLock
-  *
-  * We only get to this routine if we got SIGALRM after DeadlockTimeout
-  * while waiting for a lock to be released by some other process.  Look
-  * to see if there's a deadlock; if not, just return and continue waiting.
-  * (But signal ProcSleep to log a message, if log_lock_waits is true.)
-  * If we have a real deadlock, remove ourselves from the lock's wait queue
-  * and signal an error to ProcSleep.
-  *
-  * NB: this is run inside a signal handler, so be very wary about what is done
-  * here or in called routines.
-  */
- static void
- CheckDeadLock(void)
- {
- 	int			i;
- 
- 	/*
- 	 * Acquire exclusive lock on the entire shared lock data structures. Must
- 	 * grab LWLocks in partition-number order to avoid LWLock deadlock.
- 	 *
- 	 * Note that the deadlock check interrupt had better not be enabled
- 	 * anywhere that this process itself holds lock partition locks, else this
- 	 * will wait forever.  Also note that LWLockAcquire creates a critical
- 	 * section, so that this routine cannot be interrupted by cancel/die
- 	 * interrupts.
- 	 */
- 	for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
- 		LWLockAcquire(FirstLockMgrLock + i, LW_EXCLUSIVE);
- 
- 	/*
- 	 * Check to see if we've been awoken by anyone in the interim.
- 	 *
- 	 * If we have, we can return and resume our transaction -- happy day.
- 	 * Before we are awoken the process releasing the lock grants it to us so
- 	 * we know that we don't have to wait anymore.
- 	 *
- 	 * We check by looking to see if we've been unlinked from the wait queue.
- 	 * This is quicker than checking our semaphore's state, since no kernel
- 	 * call is needed, and it is safe because we hold the lock partition lock.
- 	 */
- 	if (MyProc->links.prev == NULL ||
- 		MyProc->links.next == NULL)
- 		goto check_done;
- 
- #ifdef LOCK_DEBUG
- 	if (Debug_deadlocks)
- 		DumpAllLocks();
- #endif
- 
- 	/* Run the deadlock check, and set deadlock_state for use by ProcSleep */
- 	deadlock_state = DeadLockCheck(MyProc);
- 
- 	if (deadlock_state == DS_HARD_DEADLOCK)
- 	{
- 		/*
- 		 * Oops.  We have a deadlock.
- 		 *
- 		 * Get this process out of wait state. (Note: we could do this more
- 		 * efficiently by relying on lockAwaited, but use this coding to
- 		 * preserve the flexibility to kill some other transaction than the
- 		 * one detecting the deadlock.)
- 		 *
- 		 * RemoveFromWaitQueue sets MyProc->waitStatus to STATUS_ERROR, so
- 		 * ProcSleep will report an error after we return from the signal
- 		 * handler.
- 		 */
- 		Assert(MyProc->waitLock != NULL);
- 		RemoveFromWaitQueue(MyProc, LockTagHashCode(&(MyProc->waitLock->tag)));
- 
- 		/*
- 		 * Unlock my semaphore so that the interrupted ProcSleep() call can
- 		 * finish.
- 		 */
- 		PGSemaphoreUnlock(&MyProc->sem);
- 
- 		/*
- 		 * We're done here.  Transaction abort caused by the error that
- 		 * ProcSleep will raise will cause any other locks we hold to be
- 		 * released, thus allowing other processes to wake up; we don't need
- 		 * to do that here.  NOTE: an exception is that releasing locks we
- 		 * hold doesn't consider the possibility of waiters that were blocked
- 		 * behind us on the lock we just failed to get, and might now be
- 		 * wakable because we're not in front of them anymore.  However,
- 		 * RemoveFromWaitQueue took care of waking up any such processes.
- 		 */
- 	}
- 	else if (log_lock_waits || deadlock_state == DS_BLOCKED_BY_AUTOVACUUM)
- 	{
- 		/*
- 		 * Unlock my semaphore so that the interrupted ProcSleep() call can
- 		 * print the log message (we daren't do it here because we are inside
- 		 * a signal handler).  It will then sleep again until someone releases
- 		 * the lock.
- 		 *
- 		 * If blocked by autovacuum, this wakeup will enable ProcSleep to send
- 		 * the canceling signal to the autovacuum worker.
- 		 */
- 		PGSemaphoreUnlock(&MyProc->sem);
- 	}
- 
- 	/*
- 	 * And release locks.  We do this in reverse order for two reasons: (1)
- 	 * Anyone else who needs more than one of the locks will be trying to lock
- 	 * them in increasing order; we don't want to release the other process
- 	 * until it can get all the locks it needs. (2) This avoids O(N^2)
- 	 * behavior inside LWLockRelease.
- 	 */
- check_done:
- 	for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
- 		LWLockRelease(FirstLockMgrLock + i);
- }
- 
- 
- /*
   * ProcWaitForSignal - wait for a signal from another backend.
   *
   * This can share the semaphore normally used for waiting for locks,
--- 1322,1327 ----
*************** ProcSendSignal(int pid)
*** 1503,1903 ****
  	if (proc != NULL)
  		PGSemaphoreUnlock(&proc->sem);
  }
- 
- 
- /*****************************************************************************
-  * SIGALRM interrupt support
-  *
-  * Maybe these should be in pqsignal.c?
-  *****************************************************************************/
- 
- /*
-  * Enable the SIGALRM interrupt to fire after the specified delay
-  *
-  * Delay is given in milliseconds.	Caller should be sure a SIGALRM
-  * signal handler is installed before this is called.
-  *
-  * This code properly handles nesting of deadlock timeout alarms within
-  * statement timeout alarms.
-  *
-  * Returns TRUE if okay, FALSE on failure.
-  */
- bool
- enable_sig_alarm(int delayms, bool is_statement_timeout)
- {
- 	TimestampTz fin_time;
- 	struct itimerval timeval;
- 
- 	if (is_statement_timeout)
- 	{
- 		/*
- 		 * Begin statement-level timeout
- 		 *
- 		 * Note that we compute statement_fin_time with reference to the
- 		 * statement_timestamp, but apply the specified delay without any
- 		 * correction; that is, we ignore whatever time has elapsed since
- 		 * statement_timestamp was set.  In the normal case only a small
- 		 * interval will have elapsed and so this doesn't matter, but there
- 		 * are corner cases (involving multi-statement query strings with
- 		 * embedded COMMIT or ROLLBACK) where we might re-initialize the
- 		 * statement timeout long after initial receipt of the message. In
- 		 * such cases the enforcement of the statement timeout will be a bit
- 		 * inconsistent.  This annoyance is judged not worth the cost of
- 		 * performing an additional gettimeofday() here.
- 		 */
- 		Assert(!deadlock_timeout_active);
- 		fin_time = GetCurrentStatementStartTimestamp();
- 		fin_time = TimestampTzPlusMilliseconds(fin_time, delayms);
- 		statement_fin_time = fin_time;
- 		cancel_from_timeout = false;
- 		statement_timeout_active = true;
- 	}
- 	else if (statement_timeout_active)
- 	{
- 		/*
- 		 * Begin deadlock timeout with statement-level timeout active
- 		 *
- 		 * Here, we want to interrupt at the closer of the two timeout times.
- 		 * If fin_time >= statement_fin_time then we need not touch the
- 		 * existing timer setting; else set up to interrupt at the deadlock
- 		 * timeout time.
- 		 *
- 		 * NOTE: in this case it is possible that this routine will be
- 		 * interrupted by the previously-set timer alarm.  This is okay
- 		 * because the signal handler will do only what it should do according
- 		 * to the state variables.	The deadlock checker may get run earlier
- 		 * than normal, but that does no harm.
- 		 */
- 		timeout_start_time = GetCurrentTimestamp();
- 		fin_time = TimestampTzPlusMilliseconds(timeout_start_time, delayms);
- 		deadlock_timeout_active = true;
- 		if (fin_time >= statement_fin_time)
- 			return true;
- 	}
- 	else
- 	{
- 		/* Begin deadlock timeout with no statement-level timeout */
- 		deadlock_timeout_active = true;
- 		/* GetCurrentTimestamp can be expensive, so only do it if we must */
- 		if (log_lock_waits)
- 			timeout_start_time = GetCurrentTimestamp();
- 	}
- 
- 	/* If we reach here, okay to set the timer interrupt */
- 	MemSet(&timeval, 0, sizeof(struct itimerval));
- 	timeval.it_value.tv_sec = delayms / 1000;
- 	timeval.it_value.tv_usec = (delayms % 1000) * 1000;
- 	if (setitimer(ITIMER_REAL, &timeval, NULL))
- 		return false;
- 	return true;
- }
- 
- /*
-  * Cancel the SIGALRM timer, either for a deadlock timeout or a statement
-  * timeout.  If a deadlock timeout is canceled, any active statement timeout
-  * remains in force.
-  *
-  * Returns TRUE if okay, FALSE on failure.
-  */
- bool
- disable_sig_alarm(bool is_statement_timeout)
- {
- 	/*
- 	 * Always disable the interrupt if it is active; this avoids being
- 	 * interrupted by the signal handler and thereby possibly getting
- 	 * confused.
- 	 *
- 	 * We will re-enable the interrupt if necessary in CheckStatementTimeout.
- 	 */
- 	if (statement_timeout_active || deadlock_timeout_active)
- 	{
- 		struct itimerval timeval;
- 
- 		MemSet(&timeval, 0, sizeof(struct itimerval));
- 		if (setitimer(ITIMER_REAL, &timeval, NULL))
- 		{
- 			statement_timeout_active = false;
- 			cancel_from_timeout = false;
- 			deadlock_timeout_active = false;
- 			return false;
- 		}
- 	}
- 
- 	/* Always cancel deadlock timeout, in case this is error cleanup */
- 	deadlock_timeout_active = false;
- 
- 	/* Cancel or reschedule statement timeout */
- 	if (is_statement_timeout)
- 	{
- 		statement_timeout_active = false;
- 		cancel_from_timeout = false;
- 	}
- 	else if (statement_timeout_active)
- 	{
- 		if (!CheckStatementTimeout())
- 			return false;
- 	}
- 	return true;
- }
- 
- 
- /*
-  * Check for statement timeout.  If the timeout time has come,
-  * trigger a query-cancel interrupt; if not, reschedule the SIGALRM
-  * interrupt to occur at the right time.
-  *
-  * Returns true if okay, false if failed to set the interrupt.
-  */
- static bool
- CheckStatementTimeout(void)
- {
- 	TimestampTz now;
- 
- 	if (!statement_timeout_active)
- 		return true;			/* do nothing if not active */
- 
- 	now = GetCurrentTimestamp();
- 
- 	if (now >= statement_fin_time)
- 	{
- 		/* Time to die */
- 		statement_timeout_active = false;
- 		cancel_from_timeout = true;
- #ifdef HAVE_SETSID
- 		/* try to signal whole process group */
- 		kill(-MyProcPid, SIGINT);
- #endif
- 		kill(MyProcPid, SIGINT);
- 	}
- 	else
- 	{
- 		/* Not time yet, so (re)schedule the interrupt */
- 		long		secs;
- 		int			usecs;
- 		struct itimerval timeval;
- 
- 		TimestampDifference(now, statement_fin_time,
- 							&secs, &usecs);
- 
- 		/*
- 		 * It's possible that the difference is less than a microsecond;
- 		 * ensure we don't cancel, rather than set, the interrupt.
- 		 */
- 		if (secs == 0 && usecs == 0)
- 			usecs = 1;
- 		MemSet(&timeval, 0, sizeof(struct itimerval));
- 		timeval.it_value.tv_sec = secs;
- 		timeval.it_value.tv_usec = usecs;
- 		if (setitimer(ITIMER_REAL, &timeval, NULL))
- 			return false;
- 	}
- 
- 	return true;
- }
- 
- 
- /*
-  * Signal handler for SIGALRM for normal user backends
-  *
-  * Process deadlock check and/or statement timeout check, as needed.
-  * To avoid various edge cases, we must be careful to do nothing
-  * when there is nothing to be done.  We also need to be able to
-  * reschedule the timer interrupt if called before end of statement.
-  */
- void
- handle_sig_alarm(SIGNAL_ARGS)
- {
- 	int			save_errno = errno;
- 
- 	/* SIGALRM is cause for waking anything waiting on the process latch */
- 	if (MyProc)
- 		SetLatch(&MyProc->procLatch);
- 
- 	if (deadlock_timeout_active)
- 	{
- 		deadlock_timeout_active = false;
- 		CheckDeadLock();
- 	}
- 
- 	if (statement_timeout_active)
- 		(void) CheckStatementTimeout();
- 
- 	errno = save_errno;
- }
- 
- /*
-  * Signal handler for SIGALRM in Startup process
-  *
-  * To avoid various edge cases, we must be careful to do nothing
-  * when there is nothing to be done.  We also need to be able to
-  * reschedule the timer interrupt if called before end of statement.
-  *
-  * We set either deadlock_timeout_active or statement_timeout_active
-  * or both. Interrupts are enabled if standby_timeout_active.
-  */
- bool
- enable_standby_sig_alarm(TimestampTz now, TimestampTz fin_time, bool deadlock_only)
- {
- 	TimestampTz deadlock_time = TimestampTzPlusMilliseconds(now,
- 															DeadlockTimeout);
- 
- 	if (deadlock_only)
- 	{
- 		/*
- 		 * Wake up at deadlock_time only, then wait forever
- 		 */
- 		statement_fin_time = deadlock_time;
- 		deadlock_timeout_active = true;
- 		statement_timeout_active = false;
- 	}
- 	else if (fin_time > deadlock_time)
- 	{
- 		/*
- 		 * Wake up at deadlock_time, then again at fin_time
- 		 */
- 		statement_fin_time = deadlock_time;
- 		statement_fin_time2 = fin_time;
- 		deadlock_timeout_active = true;
- 		statement_timeout_active = true;
- 	}
- 	else
- 	{
- 		/*
- 		 * Wake only at fin_time because its fairly soon
- 		 */
- 		statement_fin_time = fin_time;
- 		deadlock_timeout_active = false;
- 		statement_timeout_active = true;
- 	}
- 
- 	if (deadlock_timeout_active || statement_timeout_active)
- 	{
- 		long		secs;
- 		int			usecs;
- 		struct itimerval timeval;
- 
- 		TimestampDifference(now, statement_fin_time,
- 							&secs, &usecs);
- 		if (secs == 0 && usecs == 0)
- 			usecs = 1;
- 		MemSet(&timeval, 0, sizeof(struct itimerval));
- 		timeval.it_value.tv_sec = secs;
- 		timeval.it_value.tv_usec = usecs;
- 		if (setitimer(ITIMER_REAL, &timeval, NULL))
- 			return false;
- 		standby_timeout_active = true;
- 	}
- 
- 	return true;
- }
- 
- bool
- disable_standby_sig_alarm(void)
- {
- 	/*
- 	 * Always disable the interrupt if it is active; this avoids being
- 	 * interrupted by the signal handler and thereby possibly getting
- 	 * confused.
- 	 *
- 	 * We will re-enable the interrupt if necessary in CheckStandbyTimeout.
- 	 */
- 	if (standby_timeout_active)
- 	{
- 		struct itimerval timeval;
- 
- 		MemSet(&timeval, 0, sizeof(struct itimerval));
- 		if (setitimer(ITIMER_REAL, &timeval, NULL))
- 		{
- 			standby_timeout_active = false;
- 			return false;
- 		}
- 	}
- 
- 	standby_timeout_active = false;
- 
- 	return true;
- }
- 
- /*
-  * CheckStandbyTimeout() runs unconditionally in the Startup process
-  * SIGALRM handler. Timers will only be set when InHotStandby.
-  * We simply ignore any signals unless the timer has been set.
-  */
- static bool
- CheckStandbyTimeout(void)
- {
- 	TimestampTz now;
- 	bool		reschedule = false;
- 
- 	standby_timeout_active = false;
- 
- 	now = GetCurrentTimestamp();
- 
- 	/*
- 	 * Reschedule the timer if its not time to wake yet, or if we have both
- 	 * timers set and the first one has just been reached.
- 	 */
- 	if (now >= statement_fin_time)
- 	{
- 		if (deadlock_timeout_active)
- 		{
- 			/*
- 			 * We're still waiting when we reach deadlock timeout, so send out
- 			 * a request to have other backends check themselves for deadlock.
- 			 * Then continue waiting until statement_fin_time, if that's set.
- 			 */
- 			SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK);
- 			deadlock_timeout_active = false;
- 
- 			/*
- 			 * Begin second waiting period if required.
- 			 */
- 			if (statement_timeout_active)
- 			{
- 				reschedule = true;
- 				statement_fin_time = statement_fin_time2;
- 			}
- 		}
- 		else
- 		{
- 			/*
- 			 * We've now reached statement_fin_time, so ask all conflicts to
- 			 * leave, so we can press ahead with applying changes in recovery.
- 			 */
- 			SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
- 		}
- 	}
- 	else
- 		reschedule = true;
- 
- 	if (reschedule)
- 	{
- 		long		secs;
- 		int			usecs;
- 		struct itimerval timeval;
- 
- 		TimestampDifference(now, statement_fin_time,
- 							&secs, &usecs);
- 		if (secs == 0 && usecs == 0)
- 			usecs = 1;
- 		MemSet(&timeval, 0, sizeof(struct itimerval));
- 		timeval.it_value.tv_sec = secs;
- 		timeval.it_value.tv_usec = usecs;
- 		if (setitimer(ITIMER_REAL, &timeval, NULL))
- 			return false;
- 		standby_timeout_active = true;
- 	}
- 
- 	return true;
- }
- 
- void
- handle_standby_sig_alarm(SIGNAL_ARGS)
- {
- 	int			save_errno = errno;
- 
- 	if (standby_timeout_active)
- 		(void) CheckStandbyTimeout();
- 
- 	errno = save_errno;
- }
--- 1373,1375 ----
diff -dcrpN postgresql/src/backend/storage/lmgr/timeout.c postgresql.1/src/backend/storage/lmgr/timeout.c
*** postgresql/src/backend/storage/lmgr/timeout.c	1970-01-01 01:00:00.000000000 +0100
--- postgresql.1/src/backend/storage/lmgr/timeout.c	2012-05-11 09:32:17.159683077 +0200
***************
*** 0 ****
--- 1,680 ----
+ /*-------------------------------------------------------------------------
+  *
+  * timeout.c
+  *	  routines to manage timeout sources handled by SIGALRM
+  *
+  * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  *
+  * IDENTIFICATION
+  *	  src/backend/storage/lmgr/timeout.c
+  *
+  *-------------------------------------------------------------------------
+  */
+ /*
+  * Interface:
+  *		enable_timeout(),
+  *		disable_timeout(), disable_all_timeouts()
+  *		get_timeout_indicator(), get_timeout_start()
+  * and
+  *		handle_sig_alarm()
+  */
+ #include "postgres.h"
+ 
+ #include <sys/time.h>
+ 
+ #include "access/xact.h"
+ #include "miscadmin.h"
+ #include "storage/proc.h"
+ #include "storage/standby.h"
+ #include "storage/timeout.h"
+ #include "utils/timestamp.h"
+ 
+ /* GUC variables */
+ int			DeadlockTimeout = 1000;
+ int			StatementTimeout = 0;
+ 
+ /*
+  * This is used by ProcSleep() in proc.c
+  * Mark this volatile because it can be changed by the signal handler.
+  */
+ volatile DeadLockState deadlock_state = DS_NOT_YET_CHECKED;
+ 
+ 
+ /*
+  * Infrastructure for timeouts
+  */
+ 
+ static void InitDeadLock(TimestampTz start_time, TimestampTz fin_time);
+ static void DestroyDeadLock(bool keep_indicator);
+ static bool CheckDeadLock(void);
+ 
+ static void InitStatementTimeout(TimestampTz start_time, TimestampTz fin_time);
+ static void DestroyStatementTimeout(bool keep_indicator);
+ static bool CheckStatementTimeout(void);
+ 
+ static void InitStandbyDeadLock(TimestampTz start_time, TimestampTz fin_time);
+ static void DestroyStandbyDeadLock(bool keep_indicator);
+ static bool CheckStandbyDeadLock(void);
+ 
+ static void InitStandbyTimeout(TimestampTz start_time, TimestampTz fin_time);
+ static void DestroyStandbyTimeout(bool keep_indicator);
+ static bool CheckStandbyTimeout(void);
+ 
+ typedef void (*timeout_init)(TimestampTz, TimestampTz);
+ typedef void (*timeout_destroy)(bool);
+ typedef bool (*timeout_check)(void);
+ typedef TimestampTz (*timeout_start)(void);
+ 
+ typedef struct {
+ 	TimeoutName	index;
+ 	bool		resched_next;
+ 
+ 	/* volatile because it may be changed from the signal handler */
+ 	volatile bool	indicator;
+ 
+ 	timeout_init	timeout_init;
+ 	timeout_destroy	timeout_destroy;
+ 	timeout_check	timeout_check;
+ 	timeout_start	timeout_start;
+ 
+ 	TimestampTz	start_time;
+ 	TimestampTz	fin_time;
+ } timeout_params;
+ 
+ /*
+  * List of possible timeout reasons in the order of enum TimeoutName.
+  * The priority of timeouts (in case two of them would trigger at the
+  * same time) is determined by this order: the earlier one in the list
+  * has higher priority.
+  */
+ static timeout_params base_timeouts[TIMEOUT_MAX] = {
+ 	{
+ 		DEADLOCK_TIMEOUT, true, false,
+ 		InitDeadLock, DestroyDeadLock,
+ 		CheckDeadLock, GetCurrentTimestamp,
+ 		0
+ 	},
+ 
+ 	{
+ 		STATEMENT_TIMEOUT, false, false,
+ 		InitStatementTimeout, DestroyStatementTimeout,
+ 		CheckStatementTimeout, GetCurrentStatementStartTimestamp,
+ 		0
+ 	},
+ 
+ 	{
+ 		STANDBY_DEADLOCK_TIMEOUT, true, false,
+ 		InitStandbyDeadLock, DestroyStandbyDeadLock,
+ 		CheckStandbyDeadLock, GetCurrentTimestamp,
+ 		0
+ 	},
+ 
+ 	{
+ 		STANDBY_TIMEOUT, false, false,
+ 		InitStandbyTimeout, DestroyStandbyTimeout,
+ 		CheckStandbyTimeout, GetCurrentTimestamp,
+ 		0
+ 	}
+ };
+ 
+ /*
+  * List of active timeouts ordered by their fin_time and priority.
+  */
+ static int		n_timeouts = 0;
+ static timeout_params *timeouts[TIMEOUT_MAX];
+ 
+ /*****************************************************************************
+  * Internal helper functions
+  *****************************************************************************/
+ 
+ /*
+  * Find the index of a given timeout type in the active array
+  */
+ static int
+ find_active_timeout(TimeoutName tn)
+ {
+ 	int		i;
+ 
+ 	for (i = 0; i < n_timeouts; i++)
+ 	{
+ 		if (timeouts[i]->index == tn)
+ 			return i;
+ 	}
+ 
+ 	return -1;
+ }
+ 
+ #define is_timeout_active(tn)	(find_active_timeout(tn) >= 0)
+ 
+ /*
+  * Insert tn'th timeout into the list of timeouts at the given index
+  * if the previous timeout allows rescheduling the next one in the list.
+  */
+ static void
+ insert_timeout(TimeoutName tn, int index)
+ {
+ 	int	i;
+ 
+ 	if (index > 0 && !timeouts[index-1]->resched_next)
+ 		return;
+ 
+ 	for (i = n_timeouts - 1; i >= index; i--)
+ 		timeouts[i+1] = timeouts[i];
+ 
+ 	timeouts[index] = &base_timeouts[tn];
+ 	n_timeouts++;
+ }
+ 
+ /*
+  * Remove the index'th element from the timeout list.
+  */
+ static void
+ remove_timeout_index(int index)
+ {
+ 	int		i;
+ 
+ 	if (index < 0)
+ 		return;
+ 
+ 	for (i = index + 1; i < n_timeouts; i++)
+ 		timeouts[i-1] = timeouts[i];
+ 
+ 	if (n_timeouts > 0 && index < n_timeouts)
+ 		n_timeouts--;
+ }
+ 
+ /*
+  * (Re)schedule the next active timeout
+  */
+ static bool
+ schedule_timeout(TimestampTz now)
+ {
+ 	long		secs;
+ 	int			usecs;
+ 	struct itimerval timeval;
+ 
+ 	/* There is no active timeout, do nothing. */
+ 	if (n_timeouts == 0)
+ 		return true;
+ 
+ 	TimestampDifference(now, timeouts[0]->fin_time,
+ 						&secs, &usecs);
+ 
+ 	/*
+ 	 * It's possible that the difference is less than a microsecond;
+ 	 * ensure we don't cancel, rather than set, the interrupt.
+ 	 */
+ 	if (secs == 0 && usecs == 0)
+ 		usecs = 1;
+ 	MemSet(&timeval, 0, sizeof(struct itimerval));
+ 	timeval.it_value.tv_sec = secs;
+ 	timeval.it_value.tv_usec = usecs;
+ 	if (setitimer(ITIMER_REAL, &timeval, NULL))
+ 		return false;
+ 	return true;
+ }
+ 
+ /*****************************************************************************
+  * Init, Destroy and Check functions for different timeouts.
+  *
+  * NB: all Check* functions are run inside a signal handler, so be very wary
+  * about what is done in them or in called routines.
+  *****************************************************************************/
+ 
+ /*
+  * Common Init and Destroy functions
+  */
+ 
+ static void
+ InitTimeout(TimeoutName tn, TimestampTz start_time, TimestampTz fin_time)
+ {
+ 	base_timeouts[tn].indicator = false;
+ 	base_timeouts[tn].start_time = start_time;
+ 	base_timeouts[tn].fin_time = fin_time;
+ }
+ 
+ static void
+ DestroyTimeout(TimeoutName tn, bool keep_indicator)
+ {
+ 	if (!keep_indicator)
+ 		base_timeouts[tn].indicator = false;
+ 	base_timeouts[tn].start_time = 0;
+ 	base_timeouts[tn].fin_time = 0;
+ }
+ 
+ /*
+  * Functions to manage deadlock
+  */
+ 
+ static void
+ InitDeadLock(TimestampTz start_time, TimestampTz fin_time)
+ {
+ 	InitTimeout(DEADLOCK_TIMEOUT, start_time, fin_time);
+ }
+ 
+ static void
+ DestroyDeadLock(bool keep_indicator)
+ {
+ 	DestroyTimeout(DEADLOCK_TIMEOUT, keep_indicator);
+ }
+ 
+ /*
+  * CheckDeadLock
+  *
+  * Look to see if there's a deadlock; if not, just return.
+  * (But signal ProcSleep to log a message, if log_lock_waits is true.)
+  * If we have a real deadlock, remove ourselves from the lock's wait queue
+  * and signal an error to ProcSleep.
+  */
+ static bool
+ CheckDeadLock(void)
+ {
+ 	TimestampTz	now;
+ 	int			i;
+ 
+ 	now = GetCurrentTimestamp();
+ 
+ 	/* If our time has not come yet, do nothing. */
+ 	if (now < base_timeouts[DEADLOCK_TIMEOUT].fin_time)
+ 		return false;
+ 
+ 	/*
+ 	 * Acquire exclusive lock on the entire shared lock data structures. Must
+ 	 * grab LWLocks in partition-number order to avoid LWLock deadlock.
+ 	 *
+ 	 * Note that the deadlock check interrupt had better not be enabled
+ 	 * anywhere that this process itself holds lock partition locks, else this
+ 	 * will wait forever.  Also note that LWLockAcquire creates a critical
+ 	 * section, so that this routine cannot be interrupted by cancel/die
+ 	 * interrupts.
+ 	 */
+ 	for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
+ 		LWLockAcquire(FirstLockMgrLock + i, LW_EXCLUSIVE);
+ 
+ 	/*
+ 	 * Check to see if we've been awoken by anyone in the interim.
+ 	 *
+ 	 * If we have, we can return and resume our transaction -- happy day.
+ 	 * Before we are awoken the process releasing the lock grants it to us so
+ 	 * we know that we don't have to wait anymore.
+ 	 *
+ 	 * We check by looking to see if we've been unlinked from the wait queue.
+ 	 * This is quicker than checking our semaphore's state, since no kernel
+ 	 * call is needed, and it is safe because we hold the lock partition lock.
+ 	 */
+ 	if (MyProc->links.prev == NULL ||
+ 		MyProc->links.next == NULL)
+ 		goto check_done;
+ 
+ #ifdef LOCK_DEBUG
+ 	if (Debug_deadlocks)
+ 		DumpAllLocks();
+ #endif
+ 
+ 	/* Run the deadlock check, and set deadlock_state for use by ProcSleep */
+ 	deadlock_state = DeadLockCheck(MyProc);
+ 
+ 	if (deadlock_state == DS_HARD_DEADLOCK)
+ 	{
+ 		/*
+ 		 * Oops.  We have a deadlock.
+ 		 *
+ 		 * Get this process out of wait state. (Note: we could do this more
+ 		 * efficiently by relying on lockAwaited, but use this coding to
+ 		 * preserve the flexibility to kill some other transaction than the
+ 		 * one detecting the deadlock.)
+ 		 *
+ 		 * RemoveFromWaitQueue sets MyProc->waitStatus to STATUS_ERROR, so
+ 		 * ProcSleep will report an error after we return from the signal
+ 		 * handler.
+ 		 */
+ 		Assert(MyProc->waitLock != NULL);
+ 		RemoveFromWaitQueue(MyProc, LockTagHashCode(&(MyProc->waitLock->tag)));
+ 
+ 		/*
+ 		 * Unlock my semaphore so that the interrupted ProcSleep() call can
+ 		 * finish.
+ 		 */
+ 		PGSemaphoreUnlock(&MyProc->sem);
+ 
+ 		/*
+ 		 * We're done here.  Transaction abort caused by the error that
+ 		 * ProcSleep will raise will cause any other locks we hold to be
+ 		 * released, thus allowing other processes to wake up; we don't need
+ 		 * to do that here.  NOTE: an exception is that releasing locks we
+ 		 * hold doesn't consider the possibility of waiters that were blocked
+ 		 * behind us on the lock we just failed to get, and might now be
+ 		 * wakable because we're not in front of them anymore.  However,
+ 		 * RemoveFromWaitQueue took care of waking up any such processes.
+ 		 */
+ 	}
+ 	else if (log_lock_waits || deadlock_state == DS_BLOCKED_BY_AUTOVACUUM)
+ 	{
+ 		/*
+ 		 * Unlock my semaphore so that the interrupted ProcSleep() call can
+ 		 * print the log message (we daren't do it here because we are inside
+ 		 * a signal handler).  It will then sleep again until someone releases
+ 		 * the lock.
+ 		 *
+ 		 * If blocked by autovacuum, this wakeup will enable ProcSleep to send
+ 		 * the canceling signal to the autovacuum worker.
+ 		 */
+ 		PGSemaphoreUnlock(&MyProc->sem);
+ 	}
+ 
+ 	/*
+ 	 * And release locks.  We do this in reverse order for two reasons: (1)
+ 	 * Anyone else who needs more than one of the locks will be trying to lock
+ 	 * them in increasing order; we don't want to release the other process
+ 	 * until it can get all the locks it needs. (2) This avoids O(N^2)
+ 	 * behavior inside LWLockRelease.
+ 	 */
+ check_done:
+ 	for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
+ 		LWLockRelease(FirstLockMgrLock + i);
+ 
+ 	base_timeouts[DEADLOCK_TIMEOUT].indicator = true;
+ 
+ 	return true;
+ }
+ 
+ /*
+  * Functions to manage statement timeout
+  */
+ 
+ static void
+ InitStatementTimeout(TimestampTz start_time, TimestampTz fin_time)
+ {
+ 	InitTimeout(STATEMENT_TIMEOUT, start_time, fin_time);
+ }
+ 
+ static void
+ DestroyStatementTimeout(bool keep_indicator)
+ {
+ 	DestroyTimeout(STATEMENT_TIMEOUT, keep_indicator);
+ }
+ 
+ static bool
+ CheckStatementTimeout(void)
+ {
+ 	TimestampTz now;
+ 
+ 	now = GetCurrentTimestamp();
+ 
+ 	if (now < base_timeouts[STATEMENT_TIMEOUT].fin_time)
+ 		return false;
+ 
+ 	base_timeouts[STATEMENT_TIMEOUT].indicator = true;
+ #ifdef HAVE_SETSID
+ 	/* try to signal whole process group */
+ 	kill(-MyProcPid, SIGINT);
+ #endif
+ 	kill(MyProcPid, SIGINT);
+ 
+ 	return true;
+ }
+ 
+ /*
+  * Functions to manage standby deadlock functions
+  */
+ 
+ static void
+ InitStandbyDeadLock(TimestampTz start_time, TimestampTz fin_time)
+ {
+ 	InitTimeout(STANDBY_DEADLOCK_TIMEOUT, start_time, fin_time);
+ }
+ 
+ static void
+ DestroyStandbyDeadLock(bool keep_indicator)
+ {
+ 	DestroyTimeout(STANDBY_DEADLOCK_TIMEOUT, keep_indicator);
+ }
+ 
+ static bool
+ CheckStandbyDeadLock(void)
+ {
+ 	TimestampTz now;
+ 
+ 	now = GetCurrentTimestamp();
+ 
+ 	if (now < base_timeouts[STANDBY_DEADLOCK_TIMEOUT].fin_time)
+ 		return false;
+ 
+ 	base_timeouts[STANDBY_DEADLOCK_TIMEOUT].indicator = true;
+ 	SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK);
+ 	return true;
+ }
+ 
+ /*
+  * Functions to manage standby timeout
+  */
+ 
+ static void
+ InitStandbyTimeout(TimestampTz start_time, TimestampTz fin_time)
+ {
+ 	InitTimeout(STANDBY_TIMEOUT, start_time, fin_time);
+ }
+ 
+ static void
+ DestroyStandbyTimeout(bool keep_indicator)
+ {
+ 	DestroyTimeout(STANDBY_TIMEOUT, keep_indicator);
+ }
+ 
+ static bool
+ CheckStandbyTimeout(void)
+ {
+ 	TimestampTz now;
+ 
+ 	now = GetCurrentTimestamp();
+ 
+ 	if (now  < base_timeouts[STANDBY_TIMEOUT].fin_time)
+ 		return false;
+ 
+ 	base_timeouts[STANDBY_TIMEOUT].indicator = true;
+ 	SendRecoveryConflictWithBufferPin(PROCSIG_RECOVERY_CONFLICT_BUFFERPIN);
+ 	return true;
+ }
+ 
+ /*****************************************************************************
+  * Public API
+  *****************************************************************************/
+ 
+ 
+ /*
+  * Enable the SIGALRM interrupt to fire after the specified delay
+  *
+  * Delay is given in milliseconds. Caller should be sure a SIGALRM
+  * signal handler is installed before this is called.
+  *
+  * This code properly handles nesting of different timeout alarms.
+  *
+  * Returns TRUE if okay, FALSE on failure to set the timer.
+  */
+ bool
+ enable_timeout(TimeoutName tn, int delayms)
+ {
+ 	TimestampTz start_time;
+ 	TimestampTz fin_time;
+ 	int		i;
+ 
+ 	Assert(!is_timeout_active(tn));
+ 
+ 	if (delayms <= 0)
+ 		return true;
+ 
+ 	start_time = base_timeouts[tn].timeout_start();
+ 	fin_time = TimestampTzPlusMilliseconds(start_time, delayms);
+ 
+ 	/* Find out the index where to insert the new timeout. */
+ 	for (i = 0; i < n_timeouts; i++)
+ 	{
+ 		/*
+ 		 * The new timeout triggers earlier than
+ 		 * a previously added one: insert here.
+ 		 */
+ 		if (fin_time < timeouts[i]->fin_time)
+ 			break;
+ 		/*
+ 		 * The new timeout triggers at the same time
+ 		 * as the previously added one but has greater priority.
+ 		 */
+ 		if (fin_time == timeouts[i]->fin_time && tn < timeouts[i]->index)
+ 			break;
+ 	}
+ 
+ 	/*
+ 	 * Initialize the timeout parameters
+ 	 */
+ 	base_timeouts[tn].timeout_init(start_time, fin_time);
+ 
+ 	insert_timeout(tn, i);
+ 
+ 	if (i > 0)
+ 		return true;
+ 
+ 	/* If we reach here, okay to set the timer interrupt */
+ 	if (!schedule_timeout(start_time))
+ 		return false;
+ 	return true;
+ }
+ 
+ /*
+  * Cancel the SIGALRM timer for the specific timeout.
+  * If a timeout is canceled, any other active timeout remains in force.
+  *
+  * Returns TRUE if okay, FALSE on failure to set the timer for
+  * the next timeout source.
+  */
+ bool
+ disable_timeout(TimeoutName tn, bool keep_indicator)
+ {
+ 	int		i;
+ 
+ 	/*
+ 	 * Always disable the interrupt if it is active; this avoids being
+ 	 * interrupted by the signal handler and thereby possibly getting
+ 	 * confused.
+ 	 *
+ 	 * We will re-enable the interrupt if necessary in ->check_timeout().
+ 	 */
+ 	if (n_timeouts > 0)
+ 	{
+ 		struct itimerval timeval;
+ 
+ 		MemSet(&timeval, 0, sizeof(struct itimerval));
+ 		if (setitimer(ITIMER_REAL, &timeval, NULL))
+ 		{
+ 			n_timeouts = 0;
+ 			for (i = 0; i < TIMEOUT_MAX; i++)
+ 				base_timeouts[i].timeout_destroy(false);
+ 
+ 			return false;
+ 		}
+ 	}
+ 
+ 	/* Find the timeout and remove from the list. */
+ 	i = find_active_timeout(tn);
+ 	remove_timeout_index(i);
+ 
+ 	/* Do cleanup. */
+ 	base_timeouts[tn].timeout_destroy(keep_indicator);
+ 
+ 	/*
+ 	 * If the first timeout was removed from the list and there is
+ 	 * at least one active left, reschedule it.
+ 	 */
+ 	if (i == 0 && n_timeouts > 0)
+ 		if (!schedule_timeout(GetCurrentTimestamp()))
+ 			return false;
+ 
+ 	return true;
+ }
+ 
+ /*
+  * Disable SIGALRM and remove all timeouts from the list and
+  * reset the timeout indicators.
+  */
+ bool
+ disable_all_timeouts(bool keep_indicators)
+ {
+ 	struct itimerval timeval;
+ 	int		i;
+ 	bool		ret;
+ 
+ 	MemSet(&timeval, 0, sizeof(struct itimerval));
+ 	ret = (setitimer(ITIMER_REAL, &timeval, NULL) == 0);
+ 
+ 	n_timeouts = 0;
+ 	for (i = 0; i < TIMEOUT_MAX; i++)
+ 		base_timeouts[i].timeout_destroy(keep_indicators);
+ 
+ 	return ret;
+ }
+ 
+ /*
+  * Return the timeout indicator
+  */
+ bool
+ get_timeout_indicator(TimeoutName tn)
+ {
+ 	return base_timeouts[tn].indicator;
+ }
+ 
+ /*
+  * Return the start of the timer for this timeout
+  */
+ TimestampTz
+ get_timeout_start(TimeoutName tn)
+ {
+ 	return base_timeouts[tn].start_time;
+ }
+ 
+ /*
+  * Signal handler for SIGALRM
+  *
+  * Process the check for the currently active timeout source and
+  * reschedule the next as needed. To avoid various edge cases,
+  * we must be careful to do nothing when there is nothing to be done.
+  */
+ void
+ handle_sig_alarm(SIGNAL_ARGS)
+ {
+ 	int			save_errno = errno;
+ 
+ 	/*
+ 	 * SIGALRM is cause for waking anything waiting on the process latch.
+ 	 * Recovery (the startup process) doesn't have MyProc set so
+ 	 * it can also use this signal handler.
+ 	 */
+ 	if (MyProc)
+ 		SetLatch(&MyProc->procLatch);
+ 
+ 	if (n_timeouts > 0)
+ 	{
+ 		bool	ret;
+ 		bool	reschedule = true;
+ 
+ 		ret = timeouts[0]->timeout_check();
+ 
+ 		/* Shift timeouts if the timeout was triggered */
+ 		if (ret)
+ 		{
+ 			reschedule = timeouts[0]->resched_next;
+ 			/*
+ 			 * Short circuit disable_timeout(..., true) for the
+ 			 * timeout source that just triggered.
+ 			 */
+ 			remove_timeout_index(0);
+ 		}
+ 
+ 		if (reschedule)
+ 			schedule_timeout(GetCurrentTimestamp());
+ 		else
+ 			disable_all_timeouts(true);
+ 	}
+ 
+ 	errno = save_errno;
+ }
diff -dcrpN postgresql/src/backend/tcop/postgres.c postgresql.1/src/backend/tcop/postgres.c
*** postgresql/src/backend/tcop/postgres.c	2012-05-07 19:35:27.203721210 +0200
--- postgresql.1/src/backend/tcop/postgres.c	2012-05-11 09:32:17.172683149 +0200
***************
*** 64,69 ****
--- 64,70 ----
  #include "storage/proc.h"
  #include "storage/procsignal.h"
  #include "storage/sinval.h"
+ #include "storage/timeout.h"
  #include "tcop/fastpath.h"
  #include "tcop/pquery.h"
  #include "tcop/tcopprot.h"
*************** start_xact_command(void)
*** 2396,2404 ****
  		/* Set statement timeout running, if any */
  		/* NB: this mustn't be enabled until we are within an xact */
  		if (StatementTimeout > 0)
! 			enable_sig_alarm(StatementTimeout, true);
  		else
! 			cancel_from_timeout = false;
  
  		xact_started = true;
  	}
--- 2397,2405 ----
  		/* Set statement timeout running, if any */
  		/* NB: this mustn't be enabled until we are within an xact */
  		if (StatementTimeout > 0)
! 			enable_timeout(STATEMENT_TIMEOUT, StatementTimeout);
  		else
! 			disable_timeout(STATEMENT_TIMEOUT, false);
  
  		xact_started = true;
  	}
*************** finish_xact_command(void)
*** 2410,2416 ****
  	if (xact_started)
  	{
  		/* Cancel any active statement timeout before committing */
! 		disable_sig_alarm(true);
  
  		/* Now commit the command */
  		ereport(DEBUG3,
--- 2411,2417 ----
  	if (xact_started)
  	{
  		/* Cancel any active statement timeout before committing */
! 		disable_all_timeouts(false);
  
  		/* Now commit the command */
  		ereport(DEBUG3,
*************** ProcessInterrupts(void)
*** 2891,2897 ****
  					(errcode(ERRCODE_QUERY_CANCELED),
  					 errmsg("canceling authentication due to timeout")));
  		}
! 		if (cancel_from_timeout)
  		{
  			ImmediateInterruptOK = false;		/* not idle anymore */
  			DisableNotifyInterrupt();
--- 2892,2898 ----
  					(errcode(ERRCODE_QUERY_CANCELED),
  					 errmsg("canceling authentication due to timeout")));
  		}
! 		if (get_timeout_indicator(STATEMENT_TIMEOUT))
  		{
  			ImmediateInterruptOK = false;		/* not idle anymore */
  			DisableNotifyInterrupt();
*************** PostgresMain(int argc, char *argv[], con
*** 3796,3805 ****
  
  		/*
  		 * Forget any pending QueryCancel request, since we're returning to
! 		 * the idle loop anyway, and cancel the statement timer if running.
  		 */
  		QueryCancelPending = false;
! 		disable_sig_alarm(true);
  		QueryCancelPending = false;		/* again in case timeout occurred */
  
  		/*
--- 3797,3806 ----
  
  		/*
  		 * Forget any pending QueryCancel request, since we're returning to
! 		 * the idle loop anyway, and cancel the timer if running.
  		 */
  		QueryCancelPending = false;
! 		disable_all_timeouts(false);
  		QueryCancelPending = false;		/* again in case timeout occurred */
  
  		/*
diff -dcrpN postgresql/src/backend/utils/init/postinit.c postgresql.1/src/backend/utils/init/postinit.c
*** postgresql/src/backend/utils/init/postinit.c	2012-04-16 19:57:22.490916093 +0200
--- postgresql.1/src/backend/utils/init/postinit.c	2012-05-11 09:32:17.183683211 +0200
***************
*** 41,51 ****
  #include "storage/fd.h"
  #include "storage/ipc.h"
  #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 "tcop/tcopprot.h"
  #include "utils/acl.h"
  #include "utils/fmgroids.h"
--- 41,51 ----
  #include "storage/fd.h"
  #include "storage/ipc.h"
  #include "storage/lmgr.h"
  #include "storage/procarray.h"
  #include "storage/procsignal.h"
  #include "storage/sinvaladt.h"
  #include "storage/smgr.h"
+ #include "storage/timeout.h"
  #include "tcop/tcopprot.h"
  #include "utils/acl.h"
  #include "utils/fmgroids.h"
*************** PerformAuthentication(Port *port)
*** 204,210 ****
  	 * during authentication.  Since we're inside a transaction and might do
  	 * database access, we have to use the statement_timeout infrastructure.
  	 */
! 	if (!enable_sig_alarm(AuthenticationTimeout * 1000, true))
  		elog(FATAL, "could not set timer for authorization timeout");
  
  	/*
--- 204,210 ----
  	 * during authentication.  Since we're inside a transaction and might do
  	 * database access, we have to use the statement_timeout infrastructure.
  	 */
! 	if (!enable_timeout(STATEMENT_TIMEOUT, AuthenticationTimeout * 1000))
  		elog(FATAL, "could not set timer for authorization timeout");
  
  	/*
*************** PerformAuthentication(Port *port)
*** 215,221 ****
  	/*
  	 * Done with authentication.  Disable the timeout, and log if needed.
  	 */
! 	if (!disable_sig_alarm(true))
  		elog(FATAL, "could not disable timer for authorization timeout");
  
  	if (Log_connections)
--- 215,221 ----
  	/*
  	 * Done with authentication.  Disable the timeout, and log if needed.
  	 */
! 	if (!disable_timeout(STATEMENT_TIMEOUT, false))
  		elog(FATAL, "could not disable timer for authorization timeout");
  
  	if (Log_connections)
diff -dcrpN postgresql/src/backend/utils/misc/guc.c postgresql.1/src/backend/utils/misc/guc.c
*** postgresql/src/backend/utils/misc/guc.c	2012-04-30 08:18:06.650737934 +0200
--- postgresql.1/src/backend/utils/misc/guc.c	2012-05-11 09:32:17.198683295 +0200
***************
*** 63,68 ****
--- 63,69 ----
  #include "storage/standby.h"
  #include "storage/fd.h"
  #include "storage/predicate.h"
+ #include "storage/timeout.h"
  #include "tcop/tcopprot.h"
  #include "tsearch/ts_cache.h"
  #include "utils/builtins.h"
diff -dcrpN postgresql/src/include/storage/proc.h postgresql.1/src/include/storage/proc.h
*** postgresql/src/include/storage/proc.h	2012-05-10 06:03:07.768716871 +0200
--- postgresql.1/src/include/storage/proc.h	2012-05-11 09:32:17.209683356 +0200
*************** extern PGPROC *PreparedXactProcs;
*** 217,229 ****
  
  
  /* configurable options */
- extern int	DeadlockTimeout;
- extern int	StatementTimeout;
  extern bool log_lock_waits;
  
- extern volatile bool cancel_from_timeout;
- 
- 
  /*
   * Function Prototypes
   */
--- 217,224 ----
*************** extern void LockErrorCleanup(void);
*** 251,263 ****
  extern void ProcWaitForSignal(void);
  extern void ProcSendSignal(int pid);
  
- extern bool enable_sig_alarm(int delayms, bool is_statement_timeout);
- extern bool disable_sig_alarm(bool is_statement_timeout);
- extern void handle_sig_alarm(SIGNAL_ARGS);
- 
- extern bool enable_standby_sig_alarm(TimestampTz now,
- 						 TimestampTz fin_time, bool deadlock_only);
- extern bool disable_standby_sig_alarm(void);
- extern void handle_standby_sig_alarm(SIGNAL_ARGS);
- 
  #endif   /* PROC_H */
--- 246,249 ----
diff -dcrpN postgresql/src/include/storage/timeout.h postgresql.1/src/include/storage/timeout.h
*** postgresql/src/include/storage/timeout.h	1970-01-01 01:00:00.000000000 +0100
--- postgresql.1/src/include/storage/timeout.h	2012-05-11 09:32:17.219683411 +0200
***************
*** 0 ****
--- 1,38 ----
+ /*-------------------------------------------------------------------------
+  *
+  * timeout.h
+  *	  SIGALRM timeout API
+  *
+  *
+  * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * src/include/storage/timeout.h
+  *
+  *-------------------------------------------------------------------------
+  */
+ #ifndef _TIMEOUT_H_
+ #define _TIMEOUT_H_
+ 
+ #include "datatype/timestamp.h"
+ 
+ /* configurable options */
+ extern int	DeadlockTimeout;
+ extern int	StatementTimeout;
+ 
+ typedef enum TimeoutName {
+ 	DEADLOCK_TIMEOUT,
+ 	STATEMENT_TIMEOUT,
+ 	STANDBY_DEADLOCK_TIMEOUT,
+ 	STANDBY_TIMEOUT,
+ 	TIMEOUT_MAX
+ } TimeoutName;
+ 
+ extern bool enable_timeout(TimeoutName tn, int delayms);
+ extern bool disable_timeout(TimeoutName tn, bool keep_indicator);
+ extern bool disable_all_timeouts(bool keep_indicators);
+ extern bool get_timeout_indicator(TimeoutName tn);
+ extern TimestampTz get_timeout_start(TimeoutName tn);
+ extern void handle_sig_alarm(SIGNAL_ARGS);
+ 
+ #endif /* _TIMEOUT_H_ */
