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

commit 1f836c5f7394ccde8b2f502d632ac8e07835586d
Author: Takashi Yano <takashi.y...@nifty.ne.jp>
Date:   Sat Jul 19 23:49:26 2025 +0900

    Cygwin: spawn: Make system() thread-safe
    
    POSIX states system() shall be thread-safe, however, it is not in
    current cygwin. This is because ch_spawn is a global and is shared
    between threads. With this patch, system() uses ch_spawn_local
    instead which is local variable. popen() has the same problem, so
    it has been fixed in the same way.
    
    Addresses: https://cygwin.com/pipermail/cygwin/2025-June/258324.html
    Fixes: 1fd5e000ace5 ("import winsup-2000-02-17 snapshot")
    Reported-by: Takashi Yano <takashi.y...@nifty.ne.jp>
    Reviewed-by: Corinna Vinschen <cori...@vinschen.de>
    Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp>

Diff:
---
 winsup/cygwin/spawn.cc    | 3 ++-
 winsup/cygwin/syscalls.cc | 5 +++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 7f2f5a8aa..680f0fefd 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -950,6 +950,7 @@ spawnve (int mode, const char *path, const char *const 
*argv,
   if (!envp)
     envp = empty_env;
 
+  child_info_spawn ch_spawn_local (_CH_NADA, false);
   switch (_P_MODE (mode))
     {
     case _P_OVERLAY:
@@ -963,7 +964,7 @@ spawnve (int mode, const char *path, const char *const 
*argv,
     case _P_WAIT:
     case _P_DETACH:
     case _P_SYSTEM:
-      ret = ch_spawn.worker (path, argv, envp, mode);
+      ret = ch_spawn_local.worker (path, argv, envp, mode);
       break;
     default:
       set_errno (EINVAL);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index d6a2c2d3b..863f8f23c 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -4535,8 +4535,9 @@ popen (const char *command, const char *in_type)
       fcntl (stdchild, F_SETFD, stdchild_state | FD_CLOEXEC);
 
       /* Start a shell process to run the given command without forking. */
-      pid_t pid = ch_spawn.worker ("/bin/sh", argv, environ, _P_NOWAIT,
-                                  __std[0], __std[1]);
+      child_info_spawn ch_spawn_local (_CH_NADA, false);
+      pid_t pid = ch_spawn_local.worker ("/bin/sh", argv, environ, _P_NOWAIT,
+                                        __std[0], __std[1]);
 
       /* Reinstate the close-on-exec state */
       fcntl (stdchild, F_SETFD, stdchild_state);

Reply via email to