> I can confirm that your patch fixes the issue here.

Great. Thanks.

Testing showed a regression: glthread_once is no longer working on FreeBSD 11,
because in this code

# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
    (pthread_in_use ()                                                         \
     ? pthread_once (ONCE_CONTROL, INITFUNCTION)                               \
     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))

pthread_in_use () now evaluates to 1, and pthread_once from libc returns ENOSYS.
Thus glthread_once returns ENOSYS, and gl_once calls abort().

This patch fixes it.


2020-01-20  Bruno Haible  <br...@clisp.org>

        lock: Fix test-once1 failure on FreeBSD 11 (regression from 2020-01-19).
        * lib/glthread/lock.c (glthread_once_multithreaded): New function.
        * lib/glthread/lock.h (glthread_once_multithreaded): New declaration.
        (glthread_once): Use it.

diff --git a/lib/glthread/lock.c b/lib/glthread/lock.c
index 6336591..1f6f713 100644
--- a/lib/glthread/lock.c
+++ b/lib/glthread/lock.c
@@ -718,6 +718,26 @@ glthread_once_singlethreaded (pthread_once_t *once_control)
     return 0;
 }
 
+# if !(PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK)
+
+int
+glthread_once_multithreaded (pthread_once_t *once_control,
+                             void (*init_function) (void))
+{
+  int err = pthread_once (once_control, init_function);
+  if (err == ENOSYS)
+    {
+      /* This happens on FreeBSD 11: The pthread_once function in libc returns
+         ENOSYS.  */
+      if (glthread_once_singlethreaded (once_control))
+        init_function ();
+      return 0;
+    }
+  return err;
+}
+
+# endif
+
 #endif
 
 /* ========================================================================= */
diff --git a/lib/glthread/lock.h b/lib/glthread/lock.h
index 9c70f4e..1de86fe 100644
--- a/lib/glthread/lock.h
+++ b/lib/glthread/lock.h
@@ -505,10 +505,19 @@ extern int glthread_recursive_lock_destroy_multithreaded 
(gl_recursive_lock_t *l
 typedef pthread_once_t gl_once_t;
 # define gl_once_define(STORAGECLASS, NAME) \
     STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
-# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
-    (pthread_in_use ()                                                         
\
-     ? pthread_once (ONCE_CONTROL, INITFUNCTION)                               
\
-     : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 
0))
+# if PTHREAD_IN_USE_DETECTION_HARD || USE_POSIX_THREADS_WEAK
+#  define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+     (pthread_in_use ()                                                        
\
+      ? pthread_once (ONCE_CONTROL, INITFUNCTION)                              
\
+      : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 
0))
+# else
+#  define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+     (pthread_in_use ()                                                        
\
+      ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION)               
\
+      : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 
0))
+extern int glthread_once_multithreaded (pthread_once_t *once_control,
+                                        void (*init_function) (void));
+# endif
 extern int glthread_once_singlethreaded (pthread_once_t *once_control);
 
 # ifdef __cplusplus


Reply via email to