diff options
author | Noah Misch <noah@leadboat.com> | 2015-01-07 22:35:44 -0500 |
---|---|---|
committer | Noah Misch <noah@leadboat.com> | 2015-01-07 22:40:40 -0500 |
commit | 1a366d51effd0e9f3301d68c2d3dce09c8c43d1f (patch) | |
tree | ffb5cbd67055a45f36ab2e2ab1ad2fb4136d00ff /src/backend | |
parent | 230865e308f65d24d32aba1e6c1e4502b9047347 (diff) | |
download | postgresql-1a366d51effd0e9f3301d68c2d3dce09c8c43d1f.tar.gz postgresql-1a366d51effd0e9f3301d68c2d3dce09c8c43d1f.zip |
On Darwin, detect and report a multithreaded postmaster.
Darwin --enable-nls builds use a substitute setlocale() that may start a
thread. Buildfarm member orangutan experienced BackendList corruption
on account of different postmaster threads executing signal handlers
simultaneously. Furthermore, a multithreaded postmaster risks undefined
behavior from sigprocmask() and fork(). Emit LOG messages about the
problem and its workaround. Back-patch to 9.0 (all supported versions).
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/postmaster/postmaster.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 3dbf82b339d..d294f9e0af2 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -91,6 +91,10 @@ #include <dns_sd.h> #endif +#ifdef HAVE_PTHREAD_IS_THREADED_NP +#include <pthread.h> +#endif + #include "access/transam.h" #include "access/xlog.h" #include "bootstrap/bootstrap.h" @@ -1233,6 +1237,24 @@ PostmasterMain(int argc, char *argv[]) */ RemovePgTempFiles(); +#ifdef HAVE_PTHREAD_IS_THREADED_NP + + /* + * On Darwin, libintl replaces setlocale() with a version that calls + * CFLocaleCopyCurrent() when its second argument is "" and every relevant + * environment variable is unset or empty. CFLocaleCopyCurrent() makes + * the process multithreaded. The postmaster calls sigprocmask() and + * calls fork() without an immediate exec(), both of which have undefined + * behavior in a multithreaded program. A multithreaded postmaster is the + * normal case on Windows, which offers neither fork() nor sigprocmask(). + */ + if (pthread_is_threaded_np() != 0) + ereport(LOG, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("postmaster became multithreaded during startup"), + errhint("Set the LC_ALL environment variable to a valid locale."))); +#endif + /* * Remember postmaster startup time */ @@ -1675,6 +1697,15 @@ ServerLoop(void) TouchSocketLockFiles(); last_touch_time = now; } + +#ifdef HAVE_PTHREAD_IS_THREADED_NP + + /* + * With assertions enabled, check regularly for appearance of + * additional threads. All builds check at start and exit. + */ + Assert(pthread_is_threaded_np() == 0); +#endif } } @@ -4632,6 +4663,18 @@ SubPostmasterMain(int argc, char *argv[]) static void ExitPostmaster(int status) { +#ifdef HAVE_PTHREAD_IS_THREADED_NP + + /* + * There is no known cause for a postmaster to become multithreaded after + * startup. Recheck to account for the possibility of unknown causes. + */ + if (pthread_is_threaded_np() != 0) + ereport(LOG, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("postmaster became multithreaded"))); +#endif + /* should cleanup shared memory and kill all backends */ /* |