On AIX 7.3.1, I see these two test failures:

FAIL: test-thrd_create
======================

../../gltests/test-thrd_create.c:61: assertion 'ret == MAGIC' failed
FAIL test-thrd_create (exit status: 134)

FAIL: test-thrd_exit
====================

../../gltests/test-thrd_exit.c:65: assertion 'ret == MAGIC' failed
FAIL test-thrd_exit (exit status: 134)

The cause is:
  - In AIX 7.[12], the type thrd_start_t is broken, and accordingly it was
    impossible to implement thrd_join correctly, since the exit code types
    did not match.
  - In AIX 7.3.1 they fixed the thrd_start_t type. But the thrd_join is still
    broken, for no good reason.

This patch adds a workaround.


2023-08-18  Bruno Haible  <br...@clisp.org>

        thrd: Work around thrd_join bug on AIX 7.3.1.
        * m4/threads_h.m4 (gl_THREADS_H): Test against AIX 7 thrd_join bug. Set
        BROKEN_THRD_JOIN.
        (gl_THREADS_H_DEFAULTS): Initialize BROKEN_THRD_JOIN.
        * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set REPLACE_THRD_* to 1 also if
        BROKEN_THRD_JOIN is 1. Define BROKEN_THRD_START_T_OR_JOIN instead of
        BROKEN_THRD_START_T.
        * modules/threads-h (Makefile.am): Substitute BROKEN_THRD_JOIN.
        * lib/threads.in.h (rpl_thrd_t, thrd_t): Define also if BROKEN_THRD_JOIN
        is 1.
        * lib/thrd.c: Test BROKEN_THRD_START_T_OR_JOIN instead of
        BROKEN_THRD_START_T.
        * doc/posix-functions/thrd_join.texi: Update.
        * doc/posix-functions/thrd_exit.texi: Likewise.

        thrd: Refactor.
        * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Define BROKEN_THRD_JOIN_NULL, not
        BROKEN_THRD_JOIN. Rename gl_cv_func_thrd_join_works to
        gl_cv_func_thrd_join_null_works.
        * lib/thrd.c: Test BROKEN_THRD_JOIN_NULL instead of BROKEN_THRD_JOIN.

>From 51511a7a964f114eee12f34946e1b517c6e56d85 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 18 Aug 2023 21:14:40 +0200
Subject: [PATCH 1/2] thrd: Refactor.

* m4/thrd.m4 (gl_FUNC_THRD_JOIN): Define BROKEN_THRD_JOIN_NULL, not
BROKEN_THRD_JOIN. Rename gl_cv_func_thrd_join_works to
gl_cv_func_thrd_join_null_works.
* lib/thrd.c: Test BROKEN_THRD_JOIN_NULL instead of BROKEN_THRD_JOIN.
---
 ChangeLog  |  8 ++++++++
 lib/thrd.c |  2 +-
 m4/thrd.m4 | 20 ++++++++++----------
 3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b2c277f64d..7afaa9a0eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2023-08-18  Bruno Haible  <br...@clisp.org>
+
+	thrd: Refactor.
+	* m4/thrd.m4 (gl_FUNC_THRD_JOIN): Define BROKEN_THRD_JOIN_NULL, not
+	BROKEN_THRD_JOIN. Rename gl_cv_func_thrd_join_works to
+	gl_cv_func_thrd_join_null_works.
+	* lib/thrd.c: Test BROKEN_THRD_JOIN_NULL instead of BROKEN_THRD_JOIN.
+
 2023-08-18  Bruno Haible  <br...@clisp.org>
 
 	thrd tests: Add unit test for thrd_exit.
diff --git a/lib/thrd.c b/lib/thrd.c
index 9abea10a2c..d36cc894de 100644
--- a/lib/thrd.c
+++ b/lib/thrd.c
@@ -220,7 +220,7 @@ rpl_thrd_exit (int exitcode)
 
 # endif
 
-# if BROKEN_THRD_JOIN
+# if BROKEN_THRD_JOIN_NULL
 
 /* On Solaris 11.4, thrd_join crashes when the second argument is NULL.  */
 int
diff --git a/m4/thrd.m4 b/m4/thrd.m4
index fed111695f..1c0a611ae2 100644
--- a/m4/thrd.m4
+++ b/m4/thrd.m4
@@ -1,4 +1,4 @@
-# thrd.m4 serial 2
+# thrd.m4 serial 3
 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -25,8 +25,8 @@ AC_DEFUN([gl_FUNC_THRD_JOIN]
     fi
 
     dnl On Solaris 11.4, thrd_join crashes when the second argument is NULL.
-    AC_CACHE_CHECK([whether thrd_join works],
-      [gl_cv_func_thrd_join_works],
+    AC_CACHE_CHECK([whether thrd_join with NULL argument works],
+      [gl_cv_func_thrd_join_null_works],
       [save_LIBS="$LIBS"
        LIBS="$LIBS $LIBSTDTHREAD"
        AC_RUN_IFELSE(
@@ -45,22 +45,22 @@ AC_DEFUN([gl_FUNC_THRD_JOIN]
                 return 2;
               return 0;
             ]])],
-         [gl_cv_func_thrd_join_works=yes],
-         [gl_cv_func_thrd_join_works=no],
+         [gl_cv_func_thrd_join_null_works=yes],
+         [gl_cv_func_thrd_join_null_works=no],
          [case "$host_os" in
                       # Only Solaris is known to be broken.
-            solaris*) gl_cv_func_thrd_join_works="guessing no" ;;
-            *)        gl_cv_func_thrd_join_works="guessing yes" ;;
+            solaris*) gl_cv_func_thrd_join_null_works="guessing no" ;;
+            *)        gl_cv_func_thrd_join_null_works="guessing yes" ;;
           esac
          ])
        LIBS="$save_LIBS"
       ])
-    case "$gl_cv_func_thrd_join_works" in
+    case "$gl_cv_func_thrd_join_null_works" in
       *yes) ;;
       *)
         REPLACE_THRD_JOIN=1
-        AC_DEFINE([BROKEN_THRD_JOIN], [1],
-          [Define if the thrd_join function does not behave as in ISO C 11.])
+        AC_DEFINE([BROKEN_THRD_JOIN_NULL], [1],
+          [Define if the thrd_join function, when given a NULL argument, does not behave as in ISO C 11.])
         ;;
     esac
   fi
-- 
2.34.1

>From 2d963d69277dd30563312b0311af3cb53a9d142e Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 18 Aug 2023 22:38:04 +0200
Subject: [PATCH 2/2] thrd: Work around thrd_join bug on AIX 7.3.1.

* m4/threads_h.m4 (gl_THREADS_H): Test against AIX 7 thrd_join bug. Set
BROKEN_THRD_JOIN.
(gl_THREADS_H_DEFAULTS): Initialize BROKEN_THRD_JOIN.
* m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set REPLACE_THRD_* to 1 also if
BROKEN_THRD_JOIN is 1. Define BROKEN_THRD_START_T_OR_JOIN instead of
BROKEN_THRD_START_T.
* modules/threads-h (Makefile.am): Substitute BROKEN_THRD_JOIN.
* lib/threads.in.h (rpl_thrd_t, thrd_t): Define also if BROKEN_THRD_JOIN
is 1.
* lib/thrd.c: Test BROKEN_THRD_START_T_OR_JOIN instead of
BROKEN_THRD_START_T.
* doc/posix-functions/thrd_join.texi: Update.
* doc/posix-functions/thrd_exit.texi: Likewise.
---
 ChangeLog                          | 15 +++++++++++
 doc/posix-functions/thrd_exit.texi |  2 +-
 doc/posix-functions/thrd_join.texi |  2 +-
 lib/thrd.c                         |  6 +++--
 lib/threads.in.h                   |  2 ++
 m4/thrd.m4                         |  8 +++---
 m4/threads_h.m4                    | 43 +++++++++++++++++++++++++++++-
 modules/threads-h                  |  1 +
 8 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 7afaa9a0eb..f588ef0128 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 2023-08-18  Bruno Haible  <br...@clisp.org>
 
+	thrd: Work around thrd_join bug on AIX 7.3.1.
+	* m4/threads_h.m4 (gl_THREADS_H): Test against AIX 7 thrd_join bug. Set
+	BROKEN_THRD_JOIN.
+	(gl_THREADS_H_DEFAULTS): Initialize BROKEN_THRD_JOIN.
+	* m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set REPLACE_THRD_* to 1 also if
+	BROKEN_THRD_JOIN is 1. Define BROKEN_THRD_START_T_OR_JOIN instead of
+	BROKEN_THRD_START_T.
+	* modules/threads-h (Makefile.am): Substitute BROKEN_THRD_JOIN.
+	* lib/threads.in.h (rpl_thrd_t, thrd_t): Define also if BROKEN_THRD_JOIN
+	is 1.
+	* lib/thrd.c: Test BROKEN_THRD_START_T_OR_JOIN instead of
+	BROKEN_THRD_START_T.
+	* doc/posix-functions/thrd_join.texi: Update.
+	* doc/posix-functions/thrd_exit.texi: Likewise.
+
 	thrd: Refactor.
 	* m4/thrd.m4 (gl_FUNC_THRD_JOIN): Define BROKEN_THRD_JOIN_NULL, not
 	BROKEN_THRD_JOIN. Rename gl_cv_func_thrd_join_works to
diff --git a/doc/posix-functions/thrd_exit.texi b/doc/posix-functions/thrd_exit.texi
index a0e6e0983c..d212ce8d50 100644
--- a/doc/posix-functions/thrd_exit.texi
+++ b/doc/posix-functions/thrd_exit.texi
@@ -19,7 +19,7 @@
 glibc 2.27, macOS 11.1, FreeBSD 9.3, NetBSD 8.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
 @item
 The exit code provided to this function is discarded on some platforms:
-AIX 7.2.
+AIX 7.3.1.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/doc/posix-functions/thrd_join.texi b/doc/posix-functions/thrd_join.texi
index 874212a99a..06c4ce9f7f 100644
--- a/doc/posix-functions/thrd_join.texi
+++ b/doc/posix-functions/thrd_join.texi
@@ -19,7 +19,7 @@
 glibc 2.27, macOS 11.1, FreeBSD 9.3, NetBSD 8.0, OpenBSD 6.7, Minix 3.1.8, AIX 7.1, HP-UX 11.31, IRIX 6.5, Solaris 11.3, Cygwin 2.9, mingw, MSVC 14, Android 9.0.
 @item
 This function never stores an exit code on some platforms:
-AIX 7.2.
+AIX 7.3.1.
 @item
 This function crashes when the second argument is NULL on some platforms:
 Solaris 11.4.
diff --git a/lib/thrd.c b/lib/thrd.c
index d36cc894de..a71de9b8d2 100644
--- a/lib/thrd.c
+++ b/lib/thrd.c
@@ -26,13 +26,15 @@
 #if HAVE_THREADS_H
 /* Provide workarounds.  */
 
-# if BROKEN_THRD_START_T
+# if BROKEN_THRD_START_T_OR_JOIN
 
 #  undef thrd_t
 
 /* AIX 7.1..7.2 defines thrd_start_t incorrectly, namely as
    'void * (*) (void *)' instead of 'int (*) (void *)'.
-   As a consequence, its thrd_join function never stores an exit code.  */
+   As a consequence, its thrd_join function never stores an exit code.
+   AIX 7.3.1 has a corrected thrd_start_t.  But the thrd_join function still
+   never stores an exit code.  */
 
 /* The Thread-Specific Storage (TSS) key that allows to access each thread's
    'struct thrd_with_exitcode *' pointer.  */
diff --git a/lib/threads.in.h b/lib/threads.in.h
index 6d1769cc53..dbf0c40538 100644
--- a/lib/threads.in.h
+++ b/lib/threads.in.h
@@ -139,6 +139,8 @@ typedef pthread_t thrd_t;
 #if @BROKEN_THRD_START_T@
 /* Need to override thrd_start_t, to make thrd_create work.  */
 # define thrd_start_t rpl_thrd_start_t
+#endif
+#if @BROKEN_THRD_START_T@ || @BROKEN_THRD_JOIN@
 /* Need to override thrd_t, to make thrd_join work.  */
 struct thrd_with_exitcode
 {
diff --git a/m4/thrd.m4 b/m4/thrd.m4
index 1c0a611ae2..cffce1efb6 100644
--- a/m4/thrd.m4
+++ b/m4/thrd.m4
@@ -1,4 +1,4 @@
-# thrd.m4 serial 3
+# thrd.m4 serial 4
 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -10,15 +10,15 @@ AC_DEFUN([gl_FUNC_THRD_JOIN]
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
 
   if test $ac_cv_header_threads_h = yes; then
-    if test $BROKEN_THRD_START_T = 1; then
+    if test $BROKEN_THRD_START_T = 1 || test $BROKEN_THRD_JOIN = 1; then
       REPLACE_THRD_CREATE=1
       REPLACE_THRD_CURRENT=1
       REPLACE_THRD_DETACH=1
       REPLACE_THRD_EQUAL=1
       REPLACE_THRD_EXIT=1
       REPLACE_THRD_JOIN=1
-      AC_DEFINE([BROKEN_THRD_START_T], [1],
-        [Define if the thrd_start_t type is not as described in ISO C 11.])
+      AC_DEFINE([BROKEN_THRD_START_T_OR_JOIN], [1],
+        [Define if the thrd_start_t type is not as described in ISO C 11 or if thrd_join discards the thread's exit code.])
       dnl The thrd_exit replacement relies on pthread_exit, which on AIX is in
       dnl libpthread.
       LIBSTDTHREAD="$LIBSTDTHREAD $LIBPTHREAD"
diff --git a/m4/threads_h.m4 b/m4/threads_h.m4
index f74c146173..1c63c7e1b7 100644
--- a/m4/threads_h.m4
+++ b/m4/threads_h.m4
@@ -1,4 +1,4 @@
-# threads_h.m4 serial 12
+# threads_h.m4 serial 13
 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -45,6 +45,46 @@ AC_DEFUN_ONCE([gl_THREADS_H]
       ])
     if test $gl_cv_thrd_start_t_correct != yes; then
       BROKEN_THRD_START_T=1
+    else
+      dnl On AIX 7.3.1, thrd_join still never stores an exit code.
+      AC_CACHE_CHECK([whether thrd_join works],
+        [gl_cv_func_thrd_join_works],
+        [save_LIBS="$LIBS"
+         LIBS="$LIBS $LIBSTDTHREAD"
+         AC_RUN_IFELSE(
+           [AC_LANG_PROGRAM(
+              [[#include <stddef.h>
+                #include <threads.h>
+                #define MAGIC 1266074729
+                static int func (void *arg)
+                {
+                  return MAGIC;
+                }
+              ]],
+              [[thrd_t thread;
+                if (thrd_create (&thread, func, NULL) != thrd_success)
+                  return 1;
+                int ret = 0xDEADBEEF;
+                if (thrd_join (thread, &ret) != thrd_success)
+                  return 2;
+                if (ret != MAGIC)
+                  return (ret == 0xDEADBEEF ? 3 : 4);
+                return 0;
+              ]])],
+           [gl_cv_func_thrd_join_works=yes],
+           [gl_cv_func_thrd_join_works=no],
+           [case "$host_os" in
+                    # Only AIX is known to be broken.
+              aix*) gl_cv_func_thrd_join_works="guessing no" ;;
+              *)    gl_cv_func_thrd_join_works="guessing yes" ;;
+            esac
+           ])
+         LIBS="$save_LIBS"
+        ])
+      case "$gl_cv_func_thrd_join_works" in
+        *yes) ;;
+        *) BROKEN_THRD_JOIN=1 ;;
+      esac
     fi
   fi
 
@@ -170,6 +210,7 @@ AC_DEFUN([gl_THREADS_H_DEFAULTS]
 [
   dnl Assume proper GNU behavior unless another module says otherwise.
   HAVE_THREAD_LOCAL=1;    AC_SUBST([HAVE_THREAD_LOCAL])
+  BROKEN_THRD_JOIN=0;     AC_SUBST([BROKEN_THRD_JOIN])
   BROKEN_THRD_START_T=0;  AC_SUBST([BROKEN_THRD_START_T])
   REPLACE_THRD_CREATE=0;  AC_SUBST([REPLACE_THRD_CREATE])
   REPLACE_THRD_CURRENT=0; AC_SUBST([REPLACE_THRD_CURRENT])
diff --git a/modules/threads-h b/modules/threads-h
index 2056df01f0..8e9da83eee 100644
--- a/modules/threads-h
+++ b/modules/threads-h
@@ -56,6 +56,7 @@ threads.h: threads.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(_NORETURN_H
 	      -e 's/@''GNULIB_THRD''@/$(GNULIB_THRD)/g' \
 	      -e 's/@''GNULIB_TSS''@/$(GNULIB_TSS)/g' \
 	      -e 's|@''HAVE_THREAD_LOCAL''@|$(HAVE_THREAD_LOCAL)|g' \
+	      -e 's|@''BROKEN_THRD_JOIN''@|$(BROKEN_THRD_JOIN)|g' \
 	      -e 's|@''BROKEN_THRD_START_T''@|$(BROKEN_THRD_START_T)|g' \
 	      -e 's|@''REPLACE_THRD_CREATE''@|$(REPLACE_THRD_CREATE)|g' \
 	      -e 's|@''REPLACE_THRD_CURRENT''@|$(REPLACE_THRD_CURRENT)|g' \
-- 
2.34.1

Reply via email to