...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 <cori...@vinschen.de> Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp> --- 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 (); -- 2.45.1