From ee67c92f2ad13681063ea46e2adf49b8a2a458a6 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 7 Mar 2019 09:08:57 +1300
Subject: [PATCH 1/2] Test __isthreaded on FreeBSD and friends.

We check macOS's pthread_is_threaded_np() function in a couple of
places to find out about libraries that might create threads
unexpectedly.  FreeBSD's exports a global variable for the same
purpose, so add support for checking that.

Discussion: https://postgr.es/m/CAMVYW_6Ee-cYdpZ%2B%2BVLnab_-3hmcorOA_kmBtsnw2R%2Bn0nVxMw%40mail.gmail.com
---
 configure                           | 12 ++++++++++++
 configure.in                        |  1 +
 src/backend/postmaster/postmaster.c | 12 ++++++------
 src/include/c.h                     | 11 +++++++++++
 src/include/pg_config.h.in          |  4 ++++
 5 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/configure b/configure
index 806810817d..d2a0033328 100755
--- a/configure
+++ b/configure
@@ -15758,6 +15758,18 @@ $as_echo "#define HAVE_PS_STRINGS 1" >>confdefs.h
 
 fi
 
+ac_fn_c_check_decl "$LINENO" "__isthreaded" "ac_cv_have_decl___isthreaded" "#include <stdio.h>
+"
+if test "x$ac_cv_have_decl___isthreaded" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL___ISTHREADED $ac_have_decl
+_ACEOF
+
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for isinf" >&5
 $as_echo_n "checking for isinf... " >&6; }
diff --git a/configure.in b/configure.in
index 9c7a9738bc..8ed0c81cc3 100644
--- a/configure.in
+++ b/configure.in
@@ -1696,6 +1696,7 @@ if test "$pgac_cv_var_PS_STRINGS" = yes ; then
   AC_DEFINE([HAVE_PS_STRINGS], 1, [Define to 1 if the PS_STRINGS thing exists.])
 fi
 
+AC_CHECK_DECLS(__isthreaded, [], [], [#include <stdio.h>])
 
 dnl Cannot use AC_CHECK_FUNC because isinf may be a macro
 AC_CACHE_CHECK([for isinf], ac_cv_func_isinf,
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index ccea231e98..a95531f9de 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -1333,7 +1333,7 @@ PostmasterMain(int argc, char *argv[])
 		 */
 	}
 
-#ifdef HAVE_PTHREAD_IS_THREADED_NP
+#ifdef HAVE_PG_IS_THREADED
 
 	/*
 	 * On macOS, libintl replaces setlocale() with a version that calls
@@ -1344,7 +1344,7 @@ PostmasterMain(int argc, char *argv[])
 	 * 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)
+	if (pg_is_threaded() != 0)
 		ereport(FATAL,
 				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
 				 errmsg("postmaster became multithreaded during startup"),
@@ -1779,13 +1779,13 @@ ServerLoop(void)
 		if (StartWorkerNeeded || HaveCrashedWorker)
 			maybe_start_bgworkers();
 
-#ifdef HAVE_PTHREAD_IS_THREADED_NP
+#ifdef HAVE_PG_IS_THREADED
 
 		/*
 		 * With assertions enabled, check regularly for appearance of
 		 * additional threads.  All builds check at start and exit.
 		 */
-		Assert(pthread_is_threaded_np() == 0);
+		Assert(pg_is_threaded() == 0);
 #endif
 
 		/*
@@ -4996,7 +4996,7 @@ SubPostmasterMain(int argc, char *argv[])
 static void
 ExitPostmaster(int status)
 {
-#ifdef HAVE_PTHREAD_IS_THREADED_NP
+#ifdef HAVE_PG_IS_THREADED
 
 	/*
 	 * There is no known cause for a postmaster to become multithreaded after
@@ -5004,7 +5004,7 @@ ExitPostmaster(int status)
 	 * This message uses LOG level, because an unclean shutdown at this point
 	 * would usually not look much different from a clean shutdown.
 	 */
-	if (pthread_is_threaded_np() != 0)
+	if (pg_is_threaded() != 0)
 		ereport(LOG,
 				(errcode(ERRCODE_INTERNAL_ERROR),
 				 errmsg_internal("postmaster became multithreaded"),
diff --git a/src/include/c.h b/src/include/c.h
index 658be50e0d..7688cb5f56 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -1257,6 +1257,17 @@ extern unsigned long long strtoull(const char *str, char **endptr, int base);
 #define NON_EXEC_STATIC static
 #endif
 
+/* macOS has a function to report if the process is multithreaded */
+#ifdef HAVE_PTHREAD_IS_THREADED_NP
+#define pg_is_threaded() pthread_is_threaded_np()
+#define HAVE_PG_IS_THREADED 1
+#endif
+/* several BSDs have a global variable instead */
+#ifdef HAVE_DECL___ISTHREADED
+#define pg_is_threaded() __isthreaded
+#define HAVE_PG_IS_THREADED 1
+#endif
+
 /* /port compatibility functions */
 #include "port.h"
 
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 6cd4cfed0a..8716b14ca0 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -192,6 +192,10 @@
    don't. */
 #undef HAVE_DECL_STRTOULL
 
+/* Define to 1 if you have the declaration of `__isthreaded', and to 0 if you
+   don't. */
+#undef HAVE_DECL___ISTHREADED
+
 /* Define to 1 if you have the `dlopen' function. */
 #undef HAVE_DLOPEN
 
-- 
2.21.0

