Fix detection and handling of strchrnul() for macOS 15.4.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 1 Apr 2025 20:49:51 +0000 (16:49 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 1 Apr 2025 20:49:51 +0000 (16:49 -0400)
As of 15.4, macOS has strchrnul(), but access to it is blocked behind
a check for MACOSX_DEPLOYMENT_TARGET >= 15.4.  But our does-it-link
configure check finds it, so we try to use it, and fail with the
present default deployment target (namely 15.0).  This accounts for
today's buildfarm failures on indri and sifaka.

This is the identical problem that we faced some years ago when Apple
introduced preadv and pwritev in the same way.  We solved that in
commit f014b1b9b by using AC_CHECK_DECLS instead of AC_CHECK_FUNCS
to check the functions' availability.  So do the same now for
strchrnul().  Interestingly, we already had a workaround for
"the link check doesn't agree with <string.h>" cases with glibc,
which we no longer need since only the header declaration is being
checked.

Testing this revealed that the meson version of this check has never
worked, because it failed to use "-Werror=unguarded-availability-new".
(Apparently nobody's tried to build with meson on macOS versions that
lack preadv/pwritev as standard.)  Adjust that while at it.  Also,
we had never put support for "-Werror=unguarded-availability-new"
into v13, but we need that now.

Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us>
Co-authored-by: Peter Eisentraut <peter@eisentraut.org>
Discussion: https://postgr.es/m/385134.1743523038@sss.pgh.pa.us
Backpatch-through: 13

configure
configure.ac
src/include/pg_config.h.in
src/port/snprintf.c
src/tools/msvc/Solution.pm

index fa9085b1c0ddec903da818bb0bcec2f70fad1332..33bc3203b36b03a4ac2ffecbda53b08c5fb7e25b 100755 (executable)
--- a/configure
+++ b/configure
@@ -16037,7 +16037,7 @@ fi
 LIBS_including_readline="$LIBS"
 LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
 
-for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink readv setproctitle setproctitle_fast setsid shm_open strchrnul strsignal symlink syncfs sync_file_range uselocale wcstombs_l writev
+for ac_func in backtrace_symbols clock_gettime copyfile fdatasync getifaddrs getpeerucred getrlimit kqueue mbstowcs_l memset_s poll posix_fallocate ppoll pstat pthread_is_threaded_np readlink readv setproctitle setproctitle_fast setsid shm_open strsignal symlink syncfs sync_file_range uselocale wcstombs_l writev
 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"
@@ -16601,6 +16601,18 @@ esac
 
 fi
 
+ac_fn_c_check_decl "$LINENO" "strchrnul" "ac_cv_have_decl_strchrnul" "#include <string.h>
+"
+if test "x$ac_cv_have_decl_strchrnul" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_STRCHRNUL $ac_have_decl
+_ACEOF
+
 
 # This is probably only present on macOS, but may as well check always
 ac_fn_c_check_decl "$LINENO" "F_FULLFSYNC" "ac_cv_have_decl_F_FULLFSYNC" "#include <fcntl.h>
index 35dc9f74b73698034e7a1d97b037049eaa70dd6a..53d341c1751252e37c46d7ef00d0ab63492d8c70 100644 (file)
@@ -1807,7 +1807,6 @@ AC_CHECK_FUNCS(m4_normalize([
    setproctitle_fast
    setsid
    shm_open
-   strchrnul
    strsignal
    symlink
    syncfs
@@ -1849,6 +1848,7 @@ AC_CHECK_DECLS([strlcat, strlcpy, strnlen])
 # won't handle deployment target restrictions on macOS
 AC_CHECK_DECLS([preadv], [], [AC_LIBOBJ(preadv)], [#include <sys/uio.h>])
 AC_CHECK_DECLS([pwritev], [], [AC_LIBOBJ(pwritev)], [#include <sys/uio.h>])
+AC_CHECK_DECLS([strchrnul], [], [], [#include <string.h>])
 
 # This is probably only present on macOS, but may as well check always
 AC_CHECK_DECLS(F_FULLFSYNC, [], [], [#include <fcntl.h>])
index d9ef9a41bf29850b85444697a23f8f059bba3fc2..605c830a1b2849f443c5471000f215b112ead869 100644 (file)
    don't. */
 #undef HAVE_DECL_RTLD_NOW
 
+/* Define to 1 if you have the declaration of `strchrnul', and to 0 if you
+   don't. */
+#undef HAVE_DECL_STRCHRNUL
+
 /* Define to 1 if you have the declaration of `strlcat', and to 0 if you
    don't. */
 #undef HAVE_DECL_STRLCAT
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
-/* Define to 1 if you have the `strchrnul' function. */
-#undef HAVE_STRCHRNUL
-
 /* Define to 1 if you have the `strerror_r' function. */
 #undef HAVE_STRERROR_R
 
index 8306ab4f2b8dcffe6469474e174f5f0d20a513ae..79c5f523bf16dd577dda1038ae975f8b591e3c2e 100644 (file)
@@ -348,13 +348,22 @@ static void leading_pad(int zpad, int signvalue, int *padlen,
 static void trailing_pad(int padlen, PrintfTarget *target);
 
 /*
- * If strchrnul exists (it's a glibc-ism), it's a good bit faster than the
- * equivalent manual loop.  If it doesn't exist, provide a replacement.
+ * If strchrnul exists (it's a glibc-ism, but since adopted by some other
+ * platforms), it's a good bit faster than the equivalent manual loop.
+ * Use it if possible, and if it doesn't exist, use this replacement.
  *
  * Note: glibc declares this as returning "char *", but that would require
  * casting away const internally, so we don't follow that detail.
+ *
+ * Note: macOS has this too as of Sequoia 15.4, but it's hidden behind
+ * a deployment-target check that causes compile errors if the deployment
+ * target isn't high enough.  So !HAVE_DECL_STRCHRNUL may mean "yes it's
+ * declared, but it doesn't compile".  To avoid failing in that scenario,
+ * use a macro to avoid matching <string.h>'s name.
  */
-#ifndef HAVE_STRCHRNUL
+#if !HAVE_DECL_STRCHRNUL
+
+#define strchrnul pg_strchrnul
 
 static inline const char *
 strchrnul(const char *s, int c)
@@ -364,19 +373,7 @@ strchrnul(const char *s, int c)
    return s;
 }
 
-#else
-
-/*
- * glibc's <string.h> declares strchrnul only if _GNU_SOURCE is defined.
- * While we typically use that on glibc platforms, configure will set
- * HAVE_STRCHRNUL whether it's used or not.  Fill in the missing declaration
- * so that this file will compile cleanly with or without _GNU_SOURCE.
- */
-#ifndef _GNU_SOURCE
-extern char *strchrnul(const char *s, int c);
-#endif
-
-#endif                         /* HAVE_STRCHRNUL */
+#endif                         /* !HAVE_DECL_STRCHRNUL */
 
 
 /*
index f0ce2ac80403bbde68211ffe912426fa0ee198b4..040e9d98b1fefa02f6478b0f3f50a1838400ceb7 100644 (file)
@@ -248,6 +248,7 @@ sub GenerateFiles
        HAVE_DECL_PWRITEV                           => 0,
        HAVE_DECL_RTLD_GLOBAL                       => 0,
        HAVE_DECL_RTLD_NOW                          => 0,
+       HAVE_DECL_STRCHRNUL                         => 0,
        HAVE_DECL_STRLCAT                           => 0,
        HAVE_DECL_STRLCPY                           => 0,
        HAVE_DECL_STRNLEN                           => 1,
@@ -367,7 +368,6 @@ sub GenerateFiles
        HAVE_SRANDOM                             => undef,
        HAVE_STDINT_H                            => 1,
        HAVE_STDLIB_H                            => 1,
-       HAVE_STRCHRNUL                           => undef,
        HAVE_STRERROR_R                          => undef,
        HAVE_STRINGS_H                           => undef,
        HAVE_STRING_H                            => 1,