mirror of https://github.com/postgres/postgres
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).
This commit is contained in:
parent
e8f82b4163
commit
83fb1ca5cf
|
@ -11301,7 +11301,7 @@ fi
|
||||||
LIBS_including_readline="$LIBS"
|
LIBS_including_readline="$LIBS"
|
||||||
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
|
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
|
||||||
|
|
||||||
for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid shm_open sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
|
for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||||
|
|
|
@ -1280,7 +1280,7 @@ PGAC_FUNC_GETTIMEOFDAY_1ARG
|
||||||
LIBS_including_readline="$LIBS"
|
LIBS_including_readline="$LIBS"
|
||||||
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
|
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
|
||||||
|
|
||||||
AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid shm_open sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
|
AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat pthread_is_threaded_np readlink setproctitle setsid shm_open sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
|
||||||
|
|
||||||
AC_REPLACE_FUNCS(fseeko)
|
AC_REPLACE_FUNCS(fseeko)
|
||||||
case $host_os in
|
case $host_os in
|
||||||
|
|
|
@ -87,6 +87,10 @@
|
||||||
#include <dns_sd.h>
|
#include <dns_sd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PTHREAD_IS_THREADED_NP
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "access/transam.h"
|
#include "access/transam.h"
|
||||||
#include "access/xlog.h"
|
#include "access/xlog.h"
|
||||||
#include "bootstrap/bootstrap.h"
|
#include "bootstrap/bootstrap.h"
|
||||||
|
@ -1203,6 +1207,24 @@ PostmasterMain(int argc, char *argv[])
|
||||||
*/
|
*/
|
||||||
RemovePgTempFiles();
|
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
|
* Remember postmaster startup time
|
||||||
*/
|
*/
|
||||||
|
@ -1660,6 +1682,15 @@ ServerLoop(void)
|
||||||
last_touch_time = now;
|
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
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we already sent SIGQUIT to children and they are slow to shut
|
* If we already sent SIGQUIT to children and they are slow to shut
|
||||||
* down, it's time to send them SIGKILL. This doesn't happen
|
* down, it's time to send them SIGKILL. This doesn't happen
|
||||||
|
@ -4738,6 +4769,18 @@ SubPostmasterMain(int argc, char *argv[])
|
||||||
static void
|
static void
|
||||||
ExitPostmaster(int status)
|
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 */
|
/* should cleanup shared memory and kill all backends */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -556,8 +556,20 @@ set_pglocale_pgservice(const char *argv0, const char *app)
|
||||||
|
|
||||||
/* don't set LC_ALL in the backend */
|
/* don't set LC_ALL in the backend */
|
||||||
if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
|
if (strcmp(app, PG_TEXTDOMAIN("postgres")) != 0)
|
||||||
|
{
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* One could make a case for reproducing here PostmasterMain()'s test
|
||||||
|
* for whether the process is multithreaded. Unlike the postmaster,
|
||||||
|
* no frontend program calls sigprocmask() or otherwise provides for
|
||||||
|
* mutual exclusion between signal handlers. While frontends using
|
||||||
|
* fork(), if multithreaded, are formally exposed to undefined
|
||||||
|
* behavior, we have not witnessed a concrete bug. Therefore,
|
||||||
|
* complaining about multithreading here may be mere pedantry.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
if (find_my_exec(argv0, my_exec_path) < 0)
|
if (find_my_exec(argv0, my_exec_path) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -372,6 +372,9 @@
|
||||||
/* Define if you have POSIX threads libraries and header files. */
|
/* Define if you have POSIX threads libraries and header files. */
|
||||||
#undef HAVE_PTHREAD
|
#undef HAVE_PTHREAD
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `pthread_is_threaded_np' function. */
|
||||||
|
#undef HAVE_PTHREAD_IS_THREADED_NP
|
||||||
|
|
||||||
/* Define to 1 if you have the <pwd.h> header file. */
|
/* Define to 1 if you have the <pwd.h> header file. */
|
||||||
#undef HAVE_PWD_H
|
#undef HAVE_PWD_H
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue