use-pselect-if-available.patch
text/x-diff
Filename: use-pselect-if-available.patch
Type: text/x-diff
Part: 1
Patch
Format: unified
| File | + | − |
|---|---|---|
| configure | 0 | 0 |
| configure.in | 0 | 0 |
| src/backend/postmaster/postmaster.c | 0 | 0 |
| src/include/pg_config.h.in | 0 | 0 |
| src/include/pg_config.h.win32 | 0 | 0 |
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 */