diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 6a6959f..b2cf973 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -10210,7 +10210,7 @@ retry:
 					/*
 					 * Wait for more WAL to arrive, or timeout to be reached
 					 */
-					WaitLatch(&XLogCtl->recoveryWakeupLatch, WL_LATCH_SET | WL_TIMEOUT, 5000000L);
+					WaitLatch(&XLogCtl->recoveryWakeupLatch, WL_LATCH_SET | WL_TIMEOUT, 5000L);
 					ResetLatch(&XLogCtl->recoveryWakeupLatch);
 				}
 				else
diff --git a/src/backend/port/unix_latch.c b/src/backend/port/unix_latch.c
index 9940a42..0663eb8 100644
--- a/src/backend/port/unix_latch.c
+++ b/src/backend/port/unix_latch.c
@@ -182,7 +182,7 @@ DisownLatch(volatile Latch *latch)
  * to wait for. If the latch is already set (and WL_LATCH_SET is given), the
  * function returns immediately.
  *
- * The 'timeout' is given in microseconds. It must be >= 0 if WL_TIMEOUT
+ * The 'timeout' is given in milliseconds. It must be >= 0 if WL_TIMEOUT
  * event is given, otherwise it is ignored. On some platforms, signals cause
  * the timeout to be restarted, so beware that the function can sleep for
  * several times longer than the specified timeout.
@@ -236,8 +236,9 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 	if (wakeEvents & WL_TIMEOUT)
 	{
 		Assert(timeout >= 0);
-		tv.tv_sec = timeout / 1000000L;
-		tv.tv_usec = timeout % 1000000L;
+		tv.tv_sec = timeout / 1000L;
+		/* tv_usec should be in microseconds */
+		tv.tv_usec = (timeout % 1000L) * 1000L;
 		tvp = &tv;
 	}
 
@@ -329,6 +330,11 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
 /*
  * Sets a latch and wakes up anyone waiting on it. Returns quickly if the
  * latch is already set.
+ *
+ * Note that there is a general requirement to call this function within
+ * signal handlers, to ensure that latch timeout is not invalidated. For
+ * generic signal handlers that may be registered for multiple processes,
+ * it will be called with the per-process latch in PGPROC as its argument.
  */
 void
 SetLatch(volatile Latch *latch)
diff --git a/src/backend/port/win32_latch.c b/src/backend/port/win32_latch.c
index 8d59ad4..5ee4f40 100644
--- a/src/backend/port/win32_latch.c
+++ b/src/backend/port/win32_latch.c
@@ -99,23 +99,14 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
 	int			numevents;
 	int			result = 0;
 	int			pmdeath_eventno = 0;
-	long		timeout_ms;
 
 	Assert(wakeEvents != 0);
+	Assert(timeout >= 0 || (wakeEvents & WL_TIMEOUT) == 0);
 
 	/* Ignore WL_SOCKET_* events if no valid socket is given */
 	if (sock == PGINVALID_SOCKET)
 		wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE);
 
-	/* Convert timeout to milliseconds for WaitForMultipleObjects() */
-	if (wakeEvents & WL_TIMEOUT)
-	{
-		Assert(timeout >= 0);
-		timeout_ms = timeout / 1000;
-	}
-	else
-		timeout_ms = INFINITE;
-
 	/* Construct an array of event handles for WaitforMultipleObjects() */
 	latchevent = latch->event;
 
@@ -162,7 +153,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
 			break;
 		}
 
-		rc = WaitForMultipleObjects(numevents, events, FALSE, timeout_ms);
+		rc = WaitForMultipleObjects(numevents, events, FALSE, (wakeEvents & WL_TIMEOUT)?timeout:INFINITE);
 
 		if (rc == WAIT_FAILED)
 			elog(ERROR, "WaitForMultipleObjects() failed: error code %d", (int) GetLastError());
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 2f3fcbf..acfc3b4 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -84,6 +84,7 @@
 #include "postmaster/postmaster.h"
 #include "storage/bufmgr.h"
 #include "storage/ipc.h"
+#include "storage/latch.h"
 #include "storage/pmsignal.h"
 #include "storage/proc.h"
 #include "storage/procsignal.h"
@@ -567,38 +568,20 @@ AutoVacLauncherMain(int argc, char *argv[])
 
 		/*
 		 * Sleep for a while according to schedule.
+		 * Wait on Latch.
 		 *
-		 * On some platforms, signals won't interrupt the sleep.  To ensure we
-		 * respond reasonably promptly when someone signals us, break down the
-		 * sleep into 1-second increments, and check for interrupts after each
-		 * nap.
+		 * We handle wait time invalidation by calling
+		 * SetLatch() in signal handlers.
 		 */
-		while (nap.tv_sec > 0 || nap.tv_usec > 0)
-		{
-			uint32		sleeptime;
-
-			if (nap.tv_sec > 0)
-			{
-				sleeptime = 1000000;
-				nap.tv_sec--;
-			}
-			else
-			{
-				sleeptime = nap.tv_usec;
-				nap.tv_usec = 0;
-			}
-			pg_usleep(sleeptime);
-
-			/*
-			 * Emergency bailout if postmaster has died.  This is to avoid the
-			 * necessity for manual cleanup of all postmaster children.
-			 */
-			if (!PostmasterIsAlive())
-				proc_exit(1);
-
-			if (got_SIGTERM || got_SIGHUP || got_SIGUSR2)
-				break;
-		}
+		WaitLatch(&MyProc->waitLatch, WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH, (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L));
+		/*
+		 * Emergency bailout if postmaster has died.  This is to avoid the
+		 * necessity for manual cleanup of all postmaster children.
+		 *
+		 * This happens again here because we may have slept for quite a while.
+		 */
+		if (!PostmasterIsAlive())
+			proc_exit(1);
 
 		DisableCatchupInterrupt();
 
@@ -1322,6 +1305,8 @@ static void
 avl_sighup_handler(SIGNAL_ARGS)
 {
 	got_SIGHUP = true;
+	/* let the waiting loop iterate */
+	SetLatch(&MyProc->waitLatch);
 }
 
 /* SIGUSR2: a worker is up and running, or just finished, or failed to fork */
@@ -1329,6 +1314,8 @@ static void
 avl_sigusr2_handler(SIGNAL_ARGS)
 {
 	got_SIGUSR2 = true;
+	/* let the waiting loop iterate */
+	SetLatch(&MyProc->waitLatch);
 }
 
 /* SIGTERM: time to die */
@@ -1336,6 +1323,8 @@ static void
 avl_sigterm_handler(SIGNAL_ARGS)
 {
 	got_SIGTERM = true;
+	/* let the waiting loop iterate */
+	SetLatch(&MyProc->waitLatch);
 }
 
 
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 2070fbb..8d1dab7 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -409,7 +409,7 @@ pgarch_MainLoop(void)
 				int rc;
 				rc = WaitLatch(&mainloop_latch,
 							   WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
-							   timeout * 1000000L);
+							   timeout * 1000L);
 				if (rc & WL_TIMEOUT)
 					wakened = true;
 			}
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index 32db2bc..4672a52 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -171,7 +171,7 @@ SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
 		 * postmaster death regularly while waiting. Note that timeout here
 		 * does not necessarily release from loop.
 		 */
-		WaitLatch(&MyProc->waitLatch, WL_LATCH_SET | WL_TIMEOUT, 60000000L);
+		WaitLatch(&MyProc->waitLatch, WL_LATCH_SET | WL_TIMEOUT, 60000L);
 
 		/* Must reset the latch before testing state. */
 		ResetLatch(&MyProc->waitLatch);
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 63a6304..c1996ca 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -812,7 +812,7 @@ WalSndLoop(void)
 			if (pq_is_send_pending())
 				wakeEvents |= WL_SOCKET_WRITEABLE;
 			WaitLatchOrSocket(&MyWalSnd->latch, wakeEvents,
-							  MyProcPort->sock, sleeptime * 1000L);
+							  MyProcPort->sock, sleeptime);
 
 			/* Check for replication timeout */
 			if (replication_timeout > 0 &&
diff --git a/src/backend/storage/ipc/procsignal.c b/src/backend/storage/ipc/procsignal.c
index 28bcaa7..892941c 100644
--- a/src/backend/storage/ipc/procsignal.c
+++ b/src/backend/storage/ipc/procsignal.c
@@ -22,6 +22,7 @@
 #include "miscadmin.h"
 #include "storage/ipc.h"
 #include "storage/latch.h"
+#include "storage/proc.h"
 #include "storage/procsignal.h"
 #include "storage/shmem.h"
 #include "storage/sinval.h"
@@ -255,6 +256,9 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
 {
 	int			save_errno = errno;
 
+	if (MyProc)
+		SetLatch(&MyProc->waitLatch);
+
 	if (CheckProcSignal(PROCSIG_CATCHUP_INTERRUPT))
 		HandleCatchupInterrupt();
 
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index f9b3028..8360bd5 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1613,6 +1613,8 @@ handle_sig_alarm(SIGNAL_ARGS)
 		(void) CheckStatementTimeout();
 
 	errno = save_errno;
+	if (MyProc)
+		SetLatch(&MyProc->waitLatch);
 }
 
 /*
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index f035a48..ec91f18 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -2643,12 +2643,12 @@ die(SIGNAL_ARGS)
 			InterruptHoldoffCount--;
 			ProcessInterrupts();
 		}
-
-		/* Interrupt any sync rep wait which is currently in progress. */
-		SetLatch(&(MyProc->waitLatch));
 	}
 
 	errno = save_errno;
+	/* set the process latch - we cannot risk invalidating its timeout */
+	if (MyProc)
+		SetLatch(&MyProc->waitLatch);
 }
 
 /*
@@ -2684,18 +2684,22 @@ StatementCancelHandler(SIGNAL_ARGS)
 			InterruptHoldoffCount--;
 			ProcessInterrupts();
 		}
-
-		/* Interrupt any sync rep wait which is currently in progress. */
-		SetLatch(&(MyProc->waitLatch));
 	}
 
 	errno = save_errno;
+	/* set the process latch - we cannot risk invalidating its timeout */
+	if (MyProc)
+		SetLatch(&MyProc->waitLatch);
 }
 
 /* signal handler for floating point exception */
 void
 FloatExceptionHandler(SIGNAL_ARGS)
 {
+	/* set the process latch - we cannot risk invalidating its timeout */
+	if (MyProc)
+		SetLatch(&MyProc->waitLatch);
+
 	ereport(ERROR,
 			(errcode(ERRCODE_FLOATING_POINT_EXCEPTION),
 			 errmsg("floating-point exception"),
@@ -2709,6 +2713,9 @@ static void
 SigHupHandler(SIGNAL_ARGS)
 {
 	got_SIGHUP = true;
+	/* set the process latch - we cannot risk invalidating its timeout */
+	if (MyProc)
+		SetLatch(&MyProc->waitLatch);
 }
 
 /*
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 09ac3cf..71e41d3 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -126,13 +126,14 @@ struct PGPROC
 	LOCKMASK	heldLocks;		/* bitmask for lock types already held on this
 								 * lock object by this backend */
 
+	Latch		waitLatch;		/* generic latch for process */
+
 	/*
 	 * Info to allow us to wait for synchronous replication, if needed.
 	 * waitLSN is InvalidXLogRecPtr if not waiting; set only by user backend.
 	 * syncRepState must not be touched except by owning process or WALSender.
 	 * syncRepLinks used only while holding SyncRepLock.
 	 */
-	Latch		waitLatch;		/* allow us to wait for sync rep */
 	XLogRecPtr	waitLSN;		/* waiting for this LSN or higher */
 	int			syncRepState;	/* wait state for sync rep */
 	SHM_QUEUE	syncRepLinks;	/* list link if process is in syncrep queue */
