On FreeBSD 11.0, I'm seeing a test failure: test-fstrcmp crashes through abort(). The reason is that the program is not linked with '-lpthread', therefore pthread_key_create() returns ENOSYS, which the code in tls.h does not expect. The real problem is that pthread_in_use() returns true, because USE_POSIX_THREADS_WEAK is not defined (see <https://lists.gnu.org/archive/html/bug-gnulib/2020-01/msg00124.html>); it should return false in this situation (in programs not linked with '-lpthread'). This patch fixes it.
2020-12-09 Bruno Haible <br...@clisp.org> threadlib: Fix test-fstrcmp failure on FreeBSD 11. * m4/threadlib.m4 (gl_THREADLIB_BODY): When weak symbols are not present on FreeBSD, define PTHREAD_IN_USE_DETECTION_HARD. * lib/glthread/threadlib.c: Include <errno.h>. (glthread_in_use): For FreeBSD, provide an alternative implementation that uses pthread_key_create. diff --git a/m4/threadlib.m4 b/m4/threadlib.m4 index 1da5fc0..e03c34f 100644 --- a/m4/threadlib.m4 +++ b/m4/threadlib.m4 @@ -1,4 +1,4 @@ -# threadlib.m4 serial 28 +# threadlib.m4 serial 29 dnl Copyright (C) 2005-2020 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -486,6 +486,17 @@ AC_DEFUN([gl_THREADLIB_BODY], AC_DEFINE([USE_POSIX_THREADS_WEAK], [1], [Define if references to the POSIX multithreading library should be made weak.]) LIBTHREAD= LTLIBTHREAD= + else + case "$host_os" in + freebsd* | dragonfly*) + if test "x$LIBTHREAD" != "x$LIBMULTITHREAD"; then + dnl If weak symbols can't tell whether pthread_create(), pthread_key_create() + dnl etc. will succeed, we need a runtime test. + AC_DEFINE([PTHREAD_IN_USE_DETECTION_HARD], [1], + [Define if the pthread_in_use() detection is hard.]) + fi + ;; + esac fi fi fi diff --git a/lib/glthread/threadlib.c b/lib/glthread/threadlib.c index 7250175..fb8aab7 100644 --- a/lib/glthread/threadlib.c +++ b/lib/glthread/threadlib.c @@ -24,11 +24,44 @@ /* Use the POSIX threads library. */ +# include <errno.h> # include <pthread.h> # include <stdlib.h> # if PTHREAD_IN_USE_DETECTION_HARD +# if defined __FreeBSD__ || defined __DragonFly__ /* FreeBSD */ + +/* Test using pthread_key_create. */ + +int +glthread_in_use (void) +{ + static int tested; + static int result; /* 1: linked with -lpthread, 0: only with libc */ + + if (!tested) + { + pthread_key_t key; + int err = pthread_key_create (&key, NULL); + + if (err == ENOSYS) + result = 0; + else + { + result = 1; + if (err == 0) + pthread_key_delete (key); + } + tested = 1; + } + return result; +} + +# else /* Solaris, HP-UX */ + +/* Test using pthread_create. */ + /* The function to be executed by a dummy thread. */ static void * dummy_thread_func (void *arg) @@ -62,6 +95,8 @@ glthread_in_use (void) return result; } +# endif + # endif #endif