diff --git a/configure b/configure
index 99d05bf..42ff097 100755
*** a/configure
--- b/configure
*************** fi
*** 12892,12898 ****
  LIBS_including_readline="$LIBS"
  LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
  
! for ac_func in cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
  do :
    as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
  ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
--- 12892,12898 ----
  LIBS_including_readline="$LIBS"
  LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
  
! for ac_func in cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pselect pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
  do :
    as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
  ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
diff --git a/configure.in b/configure.in
index c36c503..871edd8 100644
*** a/configure.in
--- b/configure.in
*************** PGAC_FUNC_WCSTOMBS_L
*** 1429,1435 ****
  LIBS_including_readline="$LIBS"
  LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
  
! AC_CHECK_FUNCS([cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
  
  AC_REPLACE_FUNCS(fseeko)
  case $host_os in
--- 1429,1435 ----
  LIBS_including_readline="$LIBS"
  LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
  
! AC_CHECK_FUNCS([cbrt clock_gettime dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pselect pstat pthread_is_threaded_np readlink setproctitle setsid shm_open symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
  
  AC_REPLACE_FUNCS(fseeko)
  case $host_os in
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 52b5e2c..382e6a8 100644
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
*************** PostmasterMain(int argc, char *argv[])
*** 613,621 ****
  	 * In the postmaster, we want to install non-ignored handlers *without*
  	 * SA_RESTART.  This is because they'll be blocked at all times except
  	 * when ServerLoop is waiting for something to happen, and during that
! 	 * window, we want signals to exit the select(2) wait so that ServerLoop
  	 * can respond if anything interesting happened.  On some platforms,
! 	 * signals marked SA_RESTART would not cause the select() wait to end.
  	 * Child processes will generally want SA_RESTART, but we expect them to
  	 * set up their own handlers before unblocking signals.
  	 *
--- 613,621 ----
  	 * In the postmaster, we want to install non-ignored handlers *without*
  	 * SA_RESTART.  This is because they'll be blocked at all times except
  	 * when ServerLoop is waiting for something to happen, and during that
! 	 * window, we want signals to exit the pselect(2) wait so that ServerLoop
  	 * can respond if anything interesting happened.  On some platforms,
! 	 * signals marked SA_RESTART would not cause the pselect() wait to end.
  	 * Child processes will generally want SA_RESTART, but we expect them to
  	 * set up their own handlers before unblocking signals.
  	 *
*************** ServerLoop(void)
*** 1669,1674 ****
--- 1669,1676 ----
  	for (;;)
  	{
  		fd_set		rmask;
+ 		fd_set	   *rmask_p;
+ 		struct timeval timeout;
  		int			selres;
  		time_t		now;
  
*************** ServerLoop(void)
*** 1678,1714 ****
  		 * We block all signals except while sleeping. That makes it safe for
  		 * signal handlers, which again block all signals while executing, to
  		 * do nontrivial work.
- 		 *
- 		 * If we are in PM_WAIT_DEAD_END state, then we don't want to accept
- 		 * any new connections, so we don't call select(), and just sleep.
  		 */
- 		memcpy((char *) &rmask, (char *) &readmask, sizeof(fd_set));
- 
  		if (pmState == PM_WAIT_DEAD_END)
  		{
! 			PG_SETMASK(&UnBlockSig);
! 
! 			pg_usleep(100000L); /* 100 msec seems reasonable */
! 			selres = 0;
! 
! 			PG_SETMASK(&BlockSig);
  		}
  		else
  		{
! 			/* must set timeout each time; some OSes change it! */
! 			struct timeval timeout;
  
  			/* Needs to run with blocked signals! */
  			DetermineSleepTime(&timeout);
  
  			PG_SETMASK(&UnBlockSig);
  
! 			selres = select(nSockets, &rmask, NULL, NULL, &timeout);
  
  			PG_SETMASK(&BlockSig);
  		}
  
! 		/* Now check the select() result */
  		if (selres < 0)
  		{
  			if (errno != EINTR && errno != EWOULDBLOCK)
--- 1680,1743 ----
  		 * We block all signals except while sleeping. That makes it safe for
  		 * signal handlers, which again block all signals while executing, to
  		 * do nontrivial work.
  		 */
  		if (pmState == PM_WAIT_DEAD_END)
  		{
! 			/*
! 			 * If we are in PM_WAIT_DEAD_END state, then we don't want to
! 			 * accept any new connections, so pass a null rmask.
! 			 */
! 			rmask_p = NULL;
! 			timeout.tv_sec = 0;
! 			timeout.tv_usec = 100000;	/* 100 msec seems reasonable */
  		}
  		else
  		{
! 			/* Normal case: check sockets, and compute a suitable timeout */
! 			memcpy(&rmask, &readmask, sizeof(fd_set));
! 			rmask_p = &rmask;
  
  			/* Needs to run with blocked signals! */
  			DetermineSleepTime(&timeout);
+ 		}
  
+ 		/*
+ 		 * We prefer to wait with pselect(2) if available, as using that,
+ 		 * together with *not* using SA_RESTART for signals, guarantees that
+ 		 * we will get kicked off the wait if a signal occurs.
+ 		 *
+ 		 * If we lack pselect(2), fake it with select(2).  This has a race
+ 		 * condition: a signal that was already pending will be delivered
+ 		 * before we reach the select(), and therefore the select() will wait,
+ 		 * even though we might wish to do something in response.  Therefore,
+ 		 * beware of putting any time-critical signal response logic into
+ 		 * ServerLoop rather than into the signal handler itself.  It will run
+ 		 * eventually, but maybe not till after a timeout delay.
+ 		 *
+ 		 * It is rumored that some implementations of pselect() are not
+ 		 * atomic, making the first alternative here functionally equivalent
+ 		 * to the second.  Not much we can do about that though.
+ 		 */
+ 		{
+ #ifdef HAVE_PSELECT
+ 			/* pselect uses a randomly different timeout API, sigh */
+ 			struct timespec ptimeout;
+ 
+ 			ptimeout.tv_sec = timeout.tv_sec;
+ 			ptimeout.tv_nsec = timeout.tv_usec * 1000;
+ 
+ 			selres = pselect(nSockets, rmask_p, NULL, NULL,
+ 							 &ptimeout, &UnBlockSig);
+ #else
  			PG_SETMASK(&UnBlockSig);
  
! 			selres = select(nSockets, rmask_p, NULL, NULL, &timeout);
  
  			PG_SETMASK(&BlockSig);
+ #endif
  		}
  
! 		/* Now check the select()/pselect() result */
  		if (selres < 0)
  		{
  			if (errno != EINTR && errno != EWOULDBLOCK)
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 03e9803..9bbf1b1 100644
*** a/src/include/pg_config.h.in
--- b/src/include/pg_config.h.in
***************
*** 400,405 ****
--- 400,408 ----
  /* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */
  #undef HAVE_PPC_LWARX_MUTEX_HINT
  
+ /* Define to 1 if you have the `pselect' function. */
+ #undef HAVE_PSELECT
+ 
  /* Define to 1 if you have the `pstat' function. */
  #undef HAVE_PSTAT
  
diff --git a/src/include/pg_config.h.win32 b/src/include/pg_config.h.win32
index f9588b0..5d36768 100644
*** a/src/include/pg_config.h.win32
--- b/src/include/pg_config.h.win32
***************
*** 267,272 ****
--- 267,275 ----
  /* Define to 1 if you have the <poll.h> header file. */
  /* #undef HAVE_POLL_H */
  
+ /* Define to 1 if you have the `pselect' function. */
+ /* #undef HAVE_PSELECT */
+ 
  /* Define to 1 if you have the `pstat' function. */
  /* #undef HAVE_PSTAT */
  
