call_once, being implemented on top of pthread_once in Cygwin, is affected
by the same bug, and needs a workaround as well.


2024-05-30  Bruno Haible  <br...@clisp.org>

        call_once: Work around Cygwin 3.5.3 bug.
        * m4/call_once.m4 (gl_FUNC_CALL_ONCE): Require AC_CANONICAL_HOST.
        On Cygwin, set REPLACE_CALL_ONCE to 1.
        * lib/call_once.c (call_once): On Cygwin, use a cast, to avoid a
        compiler warning.
        * modules/call_once (Depends-on): Add pthread-once.
        * doc/posix-functions/call_once.texi: Mention the Cygwin bug.

diff --git a/doc/posix-functions/call_once.texi 
b/doc/posix-functions/call_once.texi
index 6ae72b0d43..bf0f20ff55 100644
--- a/doc/posix-functions/call_once.texi
+++ b/doc/posix-functions/call_once.texi
@@ -22,6 +22,9 @@
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+This function makes applications hang forever on some platforms:
+Cygwin 3.5.3.
+@item
 This function does not work on some platforms:
 @c https://dev.haiku-os.org/ticket/18348
 Haiku.
diff --git a/lib/call_once.c b/lib/call_once.c
index 9ef517bdd7..54a864deda 100644
--- a/lib/call_once.c
+++ b/lib/call_once.c
@@ -53,7 +53,13 @@ call_once (once_flag *flagp, void (*func) (void))
 void
 call_once (once_flag *flagp, void (*func) (void))
 {
+# if defined __CYGWIN__
+  /* Verify that once_flag and pthread_once_t are of the same size.  */
+  struct _ { int v [sizeof (once_flag) == sizeof (pthread_once_t) ? 1 : -1]; };
+  pthread_once ((pthread_once_t *) flagp, func);
+# else
   pthread_once (flagp, func);
+# endif
 }
 
 #endif
diff --git a/m4/call_once.m4 b/m4/call_once.m4
index 0272485a91..b7919e275b 100644
--- a/m4/call_once.m4
+++ b/m4/call_once.m4
@@ -1,5 +1,5 @@
 # call_once.m4
-# serial 1
+# serial 2
 dnl Copyright (C) 2024 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,8 +8,23 @@
 AC_DEFUN([gl_FUNC_CALL_ONCE],
 [
   AC_REQUIRE([gl_THREADS_H])
+  AC_REQUIRE([AC_CANONICAL_HOST])
   gl_CHECK_FUNCS_ANDROID([call_once], [[#include <threads.h>]])
   case "$gl_cv_onwards_func_call_once" in
+    yes)
+      dnl Work around Cygwin 3.5.3 bug.
+      AC_CACHE_CHECK([whether call_once works],
+        [gl_cv_func_call_once_works],
+        [case "$host_os" in
+           cygwin*) gl_cv_func_call_once_works="guessing no" ;;
+           *)       gl_cv_func_call_once_works="yes" ;;
+         esac
+        ])
+      case "$gl_cv_func_call_once_works" in
+        *yes) ;;
+        *) REPLACE_CALL_ONCE=1 ;;
+      esac
+      ;;
     future*)
       REPLACE_CALL_ONCE=1
       ;;
diff --git a/modules/call_once b/modules/call_once
index c48847a54b..1fa4d47744 100644
--- a/modules/call_once
+++ b/modules/call_once
@@ -7,6 +7,7 @@ m4/call_once.m4
 
 Depends-on:
 threads-h
+pthread-once
 windows-once
 
 configure.ac:




Reply via email to