[newlib-cygwin/cygwin-3_6-branch] Cygwin: spawn: Lock cygheap from refresh_cygheap() until child_copy()
Takashi Yano
tyan0@sourceware.org
Wed Jul 23 10:58:06 GMT 2025
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=5af6f6f2f3b18cb825513a1e8498016af7a2fc2e
commit 5af6f6f2f3b18cb825513a1e8498016af7a2fc2e
Author: Takashi Yano <takashi.yano@nifty.ne.jp>
Date: Sat Jul 19 23:39:12 2025 +0900
Cygwin: spawn: Lock cygheap from refresh_cygheap() until child_copy()
...completion in child process because the cygheap should not be
changed to avoid mismatch between child_info::cygheap_max and
::cygheap_max. Otherwise, child_copy() might copy cygheap being
modified by other process.
In addition, to avoid deadlock, move close_all_files() for non-
Cygwin processes after unlocking cygheap, since close_all_files()
calls cfree(), which attempts to lock cygheap even when it's already
locked.
Fixes: 977ad5434cc0 ("* spawn.cc (spawn_guts): Call refresh_cygheap before creating a new process to ensure that cygheap_max is up-to-date.")
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
(cherry picked from commit 9b667234bfa6220dcca1afa1233a928d9100cfde)
Diff:
---
winsup/cygwin/spawn.cc | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index cb58b6eed..7f2f5a8aa 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -542,7 +542,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->ctty ? ::cygheap->ctty->tc_getpgid () : 0;
if (!iscygwin () && ctty_pgid && ctty_pgid != myself->pgid)
c_flags |= CREATE_NEW_PROCESS_GROUP;
- refresh_cygheap ();
if (mode == _P_DETACH)
/* all set */;
@@ -611,6 +610,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
cygpid = (mode != _P_OVERLAY) ? create_cygwin_pid () : myself->pid;
+ cygheap->lock ();
+ refresh_cygheap ();
wchar_t wcmd[(size_t) cmd];
if (!::cygheap->user.issetuid ()
|| (::cygheap->user.saved_uid == ::cygheap->user.real_uid
@@ -728,6 +729,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
::cygheap->user.reimpersonate ();
res = -1;
+ cygheap->unlock ();
__leave;
}
@@ -764,8 +766,6 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
NtClose (old_winpid_hdl);
real_path.get_wide_win32_path (myself->progname); // FIXME: race?
sigproc_printf ("new process name %W", myself->progname);
- if (!iscygwin ())
- close_all_files ();
}
else
{
@@ -781,6 +781,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
if (get_errno () != ENOMEM)
set_errno (EAGAIN);
res = -1;
+ cygheap->unlock ();
__leave;
}
child->dwProcessId = pi.dwProcessId;
@@ -816,6 +817,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
CloseHandle (pi.hProcess);
ForceCloseHandle (pi.hThread);
res = -1;
+ cygheap->unlock ();
__leave;
}
}
@@ -844,6 +846,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
/* Just mark a non-cygwin process as 'synced'. We will still eventually
wait for it to exit in maybe_set_exit_code_from_windows(). */
synced = iscygwin () ? sync (pi.dwProcessId, pi.hProcess, INFINITE) : true;
+ cygheap->unlock ();
switch (mode)
{
@@ -860,8 +863,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
}
else
{
- if (iscygwin ())
- close_all_files (true);
+ close_all_files (iscygwin ());
if (!my_wr_proc_pipe
&& WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
wait_for_myself ();
More information about the Cygwin-cvs
mailing list