I just noticed that the AIX thrd_join workaround is incomplete: The exit code of the thread may not only be provided by a 'return' statement in the thread's main function, but alternatively as an argument to thread_exit(). Thus thread_exit must be overridden as well.
Done through this patch, with a new unit test. 2023-08-18 Bruno Haible <br...@clisp.org> thrd tests: Add unit test for thrd_exit. * tests/test-thrd_exit.c: New file, based on tests/test-thrd_create.c. * modules/thrd-tests (Files): Add it. (Makefile.am): Compile and run it. thrd: On AIX 7.1 and 7.2, override also thrd_exit. * lib/threads.in.h (thrd_exit): Consider REPLACE_THRD_EXIT. * lib/thrd.c (rpl_thrd_exit): New function. * m4/threads_h.m4 (gl_THREADS_H_DEFAULTS): Initialize REPLACE_THRD_EXIT. * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set also REPLACE_THRD_EXIT and adjust LIBSTDTHREAD. * modules/threads-h (Makefile.am): Substitute REPLACE_THRD_EXIT. * doc/posix-functions/thrd_exit.texi: Mention the AIX thrd_join problem also here.
>From cdf0821487e02f833fadee1853918e9930901db1 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 18 Aug 2023 20:52:08 +0200 Subject: [PATCH 1/2] thrd: On AIX 7.1 and 7.2, override also thrd_exit. * lib/threads.in.h (thrd_exit): Consider REPLACE_THRD_EXIT. * lib/thrd.c (rpl_thrd_exit): New function. * m4/threads_h.m4 (gl_THREADS_H_DEFAULTS): Initialize REPLACE_THRD_EXIT. * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set also REPLACE_THRD_EXIT and adjust LIBSTDTHREAD. * modules/threads-h (Makefile.am): Substitute REPLACE_THRD_EXIT. * doc/posix-functions/thrd_exit.texi: Mention the AIX thrd_join problem also here. --- ChangeLog | 12 ++++++++++++ doc/posix-functions/thrd_exit.texi | 3 +++ lib/thrd.c | 15 +++++++++++++++ lib/threads.in.h | 12 ++++++++++-- m4/thrd.m4 | 6 +++++- m4/threads_h.m4 | 3 ++- modules/threads-h | 1 + 7 files changed, 48 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index e162045744..8a932dfe44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2023-08-18 Bruno Haible <br...@clisp.org> + + thrd: On AIX 7.1 and 7.2, override also thrd_exit. + * lib/threads.in.h (thrd_exit): Consider REPLACE_THRD_EXIT. + * lib/thrd.c (rpl_thrd_exit): New function. + * m4/threads_h.m4 (gl_THREADS_H_DEFAULTS): Initialize REPLACE_THRD_EXIT. + * m4/thrd.m4 (gl_FUNC_THRD_JOIN): Set also REPLACE_THRD_EXIT and adjust + LIBSTDTHREAD. + * modules/threads-h (Makefile.am): Substitute REPLACE_THRD_EXIT. + * doc/posix-functions/thrd_exit.texi: Mention the AIX thrd_join problem + also here. + 2023-08-18 Bruno Haible <br...@clisp.org> aligned_alloc: Fix test failure on AIX 7.3 with ibm-clang. diff --git a/doc/posix-functions/thrd_exit.texi b/doc/posix-functions/thrd_exit.texi index e1af16e428..a0e6e0983c 100644 --- a/doc/posix-functions/thrd_exit.texi +++ b/doc/posix-functions/thrd_exit.texi @@ -17,6 +17,9 @@ @item This function is missing on many platforms: 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. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/thrd.c b/lib/thrd.c index 5e9a988c2c..9abea10a2c 100644 --- a/lib/thrd.c +++ b/lib/thrd.c @@ -203,6 +203,21 @@ rpl_thrd_join (rpl_thrd_t thread, int *exitcodep) } } +_Noreturn void +rpl_thrd_exit (int exitcode) +{ + rpl_thrd_t t = rpl_thrd_current (); + + /* Store the exitcode, for use by thrd_join(). */ + t->exitcode = exitcode; + if (t->detached) + { + /* Clean up the thread, like thrd_join would do. */ + free (t); + } + pthread_exit (NULL); +} + # endif # if BROKEN_THRD_JOIN diff --git a/lib/threads.in.h b/lib/threads.in.h index ac87ade571..6d1769cc53 100644 --- a/lib/threads.in.h +++ b/lib/threads.in.h @@ -298,11 +298,19 @@ _GL_WARN_ON_USE (thrd_join, "thrd_join is unportable - " #endif #if @GNULIB_THRD@ -# if !@HAVE_THREADS_H@ +# if @REPLACE_THRD_EXIT@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# define thrd_exit rpl_thrd_exit +# endif +_GL_FUNCDECL_RPL (thrd_exit, _Noreturn void, (int)); +_GL_CXXALIAS_RPL (thrd_exit, void, (int)); +# else +# if !@HAVE_THREADS_H@ _GL_FUNCDECL_SYS (thrd_exit, _Noreturn void, (int)); -# endif +# endif /* Need to cast because of AIX with xlclang++. */ _GL_CXXALIAS_SYS_CAST (thrd_exit, void, (int)); +# endif _GL_CXXALIASWARN (thrd_exit); #elif defined GNULIB_POSIXCHECK # undef thrd_exit diff --git a/m4/thrd.m4 b/m4/thrd.m4 index 452629dbbb..fed111695f 100644 --- a/m4/thrd.m4 +++ b/m4/thrd.m4 @@ -1,4 +1,4 @@ -# thrd.m4 serial 1 +# thrd.m4 serial 2 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, @@ -15,9 +15,13 @@ AC_DEFUN([gl_FUNC_THRD_JOIN] 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.]) + dnl The thrd_exit replacement relies on pthread_exit, which on AIX is in + dnl libpthread. + LIBSTDTHREAD="$LIBSTDTHREAD $LIBPTHREAD" fi dnl On Solaris 11.4, thrd_join crashes when the second argument is NULL. diff --git a/m4/threads_h.m4 b/m4/threads_h.m4 index 851490c123..f74c146173 100644 --- a/m4/threads_h.m4 +++ b/m4/threads_h.m4 @@ -1,4 +1,4 @@ -# threads_h.m4 serial 11 +# threads_h.m4 serial 12 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, @@ -175,5 +175,6 @@ AC_DEFUN([gl_THREADS_H_DEFAULTS] REPLACE_THRD_CURRENT=0; AC_SUBST([REPLACE_THRD_CURRENT]) REPLACE_THRD_DETACH=0; AC_SUBST([REPLACE_THRD_DETACH]) REPLACE_THRD_EQUAL=0; AC_SUBST([REPLACE_THRD_EQUAL]) + REPLACE_THRD_EXIT=0; AC_SUBST([REPLACE_THRD_EXIT]) REPLACE_THRD_JOIN=0; AC_SUBST([REPLACE_THRD_JOIN]) ]) diff --git a/modules/threads-h b/modules/threads-h index 1a2b83a354..2056df01f0 100644 --- a/modules/threads-h +++ b/modules/threads-h @@ -61,6 +61,7 @@ threads.h: threads.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(_NORETURN_H -e 's|@''REPLACE_THRD_CURRENT''@|$(REPLACE_THRD_CURRENT)|g' \ -e 's|@''REPLACE_THRD_DETACH''@|$(REPLACE_THRD_DETACH)|g' \ -e 's|@''REPLACE_THRD_EQUAL''@|$(REPLACE_THRD_EQUAL)|g' \ + -e 's|@''REPLACE_THRD_EXIT''@|$(REPLACE_THRD_EXIT)|g' \ -e 's|@''REPLACE_THRD_JOIN''@|$(REPLACE_THRD_JOIN)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _Noreturn/r $(_NORETURN_H)' \ -- 2.34.1
>From ae27b197e07820e3d38aaad967cbd7fa9c43e006 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Fri, 18 Aug 2023 19:39:03 +0200 Subject: [PATCH 2/2] thrd tests: Add unit test for thrd_exit. * tests/test-thrd_exit.c: New file, based on tests/test-thrd_create.c. * modules/thrd-tests (Files): Add it. (Makefile.am): Compile and run it. --- ChangeLog | 5 +++ modules/thrd-tests | 6 ++-- tests/test-thrd_exit.c | 77 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 tests/test-thrd_exit.c diff --git a/ChangeLog b/ChangeLog index 8a932dfe44..b2c277f64d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2023-08-18 Bruno Haible <br...@clisp.org> + thrd tests: Add unit test for thrd_exit. + * tests/test-thrd_exit.c: New file, based on tests/test-thrd_create.c. + * modules/thrd-tests (Files): Add it. + (Makefile.am): Compile and run it. + thrd: On AIX 7.1 and 7.2, override also thrd_exit. * lib/threads.in.h (thrd_exit): Consider REPLACE_THRD_EXIT. * lib/thrd.c (rpl_thrd_exit): New function. diff --git a/modules/thrd-tests b/modules/thrd-tests index fdb6600575..c726a8df4b 100644 --- a/modules/thrd-tests +++ b/modules/thrd-tests @@ -1,6 +1,7 @@ Files: tests/test-thrd_current.c tests/test-thrd_create.c +tests/test-thrd_exit.c tests/macros.h Depends-on: @@ -8,7 +9,8 @@ Depends-on: configure.ac: Makefile.am: -TESTS += test-thrd_current test-thrd_create -check_PROGRAMS += test-thrd_current test-thrd_create +TESTS += test-thrd_current test-thrd_create test-thrd_exit +check_PROGRAMS += test-thrd_current test-thrd_create test-thrd_exit test_thrd_current_LDADD = $(LDADD) @LIBSTDTHREAD@ test_thrd_create_LDADD = $(LDADD) @LIBSTDTHREAD@ +test_thrd_exit_LDADD = $(LDADD) @LIBSTDTHREAD@ diff --git a/tests/test-thrd_exit.c b/tests/test-thrd_exit.c new file mode 100644 index 0000000000..617dfe9d09 --- /dev/null +++ b/tests/test-thrd_exit.c @@ -0,0 +1,77 @@ +/* Test of thrd_exit () function. + Copyright (C) 2011-2023 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <br...@clisp.org>, 2011. */ + +#include <config.h> + +#include <threads.h> + +#include <stdio.h> +#include <string.h> + +#include "macros.h" + +/* This test is like test-thrd_create.c, except that is uses a thrd_exit() + invocation instead of 'return' to provide the thread's result code. */ + +static thrd_t main_thread_before; +static thrd_t main_thread_after; +static thrd_t worker_thread; + +#define MAGIC 1266074729 +static volatile int work_done; + +static int +worker_thread_func (void *arg) +{ + work_done = 1; + thrd_exit (MAGIC); + return 0xBADC0DE; +} + +int +main () +{ + main_thread_before = thrd_current (); + + if (thrd_create (&worker_thread, worker_thread_func, NULL) == thrd_success) + { + int ret; + + /* Check that thrd_current () has the same value before than after the + first call to thrd_create (). */ + main_thread_after = thrd_current (); + ASSERT (memcmp (&main_thread_before, &main_thread_after, + sizeof (thrd_t)) + == 0); + + ASSERT (thrd_join (worker_thread, &ret) == thrd_success); + + /* Check the return value of the thread. */ + ASSERT (ret == MAGIC); + + /* Check that worker_thread_func () has finished executing. */ + ASSERT (work_done); + + return 0; + } + else + { + fputs ("thrd_create failed\n", stderr); + return 1; + } +} -- 2.34.1