[newlib-cygwin/cygwin-3_6-branch] Cygwin: fork: Call pthread::atforkchild () after other initializations

Takashi Yano tyan0@sourceware.org
Sat Apr 5 15:29:22 GMT 2025


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=e0bd8b4f9b7e01f852350ac8ec09166723a96871

commit e0bd8b4f9b7e01f852350ac8ec09166723a96871
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date:   Thu Apr 3 15:22:29 2025 +0900

    Cygwin: fork: Call pthread::atforkchild () after other initializations
    
    Previously, the callback registered by pthread_atfork() was called
    in pthread::atforkchild() before _my_tls.fixup_after_fork(). This
    caused misbehaviour if the callback used TLS-related functions.
    More specifically, cygwait() for a mutex at the beginning of
    fhandler_fifo_pipe::raw_write() failed because the event handle
    _my_tls.signal_arrived, which is used in cygwait() internally and
    designed to be initialized in _cygtls::fixup_after_fork(), was not
    yet initialized at that point. Due to this problem, subprocesses
    of CMake (versions >= 3.29.x) sometimes failed after the commit
    7ed9adb356df ("Cygwin: pipe: Switch pipe mode to blocking mode by
    default, 2024-09-05"). This commit triggered the issue because it
    introduced cygwait() for the mutex in fhandler_fifo_pipe::raw_write().
    
    This patch moves the pthread::atforkchild() at the end of the fork::
    child(), i.e. after all initializations for child process is finished.
    
    The reason why the issue happens not always but sometimes:
    
    The event handle signal_arrived was never properly initialized when
    fhandler_fifo_pipe::raw_write() was called from the callback. As a
    result, its value was merely copied from the parent process during
    a fork() operation. Since the event signal_arrived was not created
    as inheritable, the handle value was fundamentally invalid. Despite
    this, the issue only occurred occasionally. This inconsistency was
    due to the handle value often coinciding with other existing handles
    because of its small value, such as 0x1ac. As evidence of this, in
    many cases where the issue did not manifest, the signal_arrived
    handle was not even an event handle.
    
    Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257800.html
    Addresses: https://github.com/msys2/msys2-runtime/issues/272
    Fixes: f02b22dcee17 ("* fork.cc (frok::child): Change order of cleanup prior to return.")
    Reported-by: Christoph Reiter <reiter.christoph@gmail.com>
    Reviewed-by: Jeremy Drake <cygwin@jdrake.com>
    Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
    (cherry picked from commit 779e46b5b3ee8d0250f084d1cf2d68c0483a521e)

Diff:
---
 winsup/cygwin/fork.cc       | 2 +-
 winsup/cygwin/release/3.6.1 | 5 +++++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 783971b76..f88acdbbf 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -187,7 +187,6 @@ frok::child (volatile char * volatile here)
 
   ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
 
-  pthread::atforkchild ();
   cygbench ("fork-child");
   ld_preload ();
   fixup_hooks_after_fork ();
@@ -199,6 +198,7 @@ frok::child (volatile char * volatile here)
   CloseHandle (hParent);
   hParent = NULL;
   cygwin_finished_initializing = true;
+  pthread::atforkchild ();
   return 0;
 }
 
diff --git a/winsup/cygwin/release/3.6.1 b/winsup/cygwin/release/3.6.1
index 07a29ecce..c09a23376 100644
--- a/winsup/cygwin/release/3.6.1
+++ b/winsup/cygwin/release/3.6.1
@@ -31,3 +31,8 @@ Fixes:
 
 - Return EMFILE when opening /dev/ptmx too many times.
   Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257786.html
+
+- Move pthread::atforkchild() at the end of fork::child(). This fixes
+  subprocess failure in cmake (>= 3.29.x).
+  Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257800.html
+  Addresses: https://github.com/msys2/msys2-runtime/issues/272


More information about the Cygwin-cvs mailing list