diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/postmaster/postmaster.c | 63 | ||||
-rw-r--r-- | src/include/pg_config.h.in | 3 | ||||
-rw-r--r-- | src/include/pg_config.h.win32 | 3 |
3 files changed, 52 insertions, 17 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 5a609958896..cd793886f83 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -606,9 +606,9 @@ PostmasterMain(int argc, char *argv[]) * 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 + * 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 select() wait to end. + * 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. * @@ -1642,6 +1642,8 @@ ServerLoop(void) for (;;) { fd_set rmask; + fd_set *rmask_p; + struct timeval timeout; int selres; time_t now; @@ -1651,37 +1653,64 @@ ServerLoop(void) * 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); + /* + * 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 { - /* must set timeout each time; some OSes change it! */ - struct timeval timeout; + /* 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. + * + * Some implementations of pselect() are reportedly 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, NULL, NULL, &timeout); + selres = select(nSockets, rmask_p, NULL, NULL, &timeout); PG_SETMASK(&BlockSig); +#endif } - /* Now check the select() result */ + /* 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 7dbfa90bf49..5eabcce5da4 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -397,6 +397,9 @@ /* 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 21631870828..9288e05e07b 100644 --- a/src/include/pg_config.h.win32 +++ b/src/include/pg_config.h.win32 @@ -264,6 +264,9 @@ /* 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 */ |