...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. However, do not lock cygheap if the child process is non-cygwin process, because child_copy() will not be called in it. Not only it is unnecessary, it can also fall into deadlock in close_all_files() while cygheap is 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/local_includes/child_info.h | 10 ++++++++++ winsup/cygwin/spawn.cc | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/winsup/cygwin/local_includes/child_info.h b/winsup/cygwin/local_includes/child_info.h index 2da62ffaa..460a83684 100644 --- a/winsup/cygwin/local_includes/child_info.h +++ b/winsup/cygwin/local_includes/child_info.h @@ -191,6 +191,16 @@ public: operator HANDLE& () {return hExeced;} int worker (const char *, const char *const *, const char *const [], int, int = -1, int = -1); + inline void spawn_cygheap_lock () + { + if (iscygwin ()) + cygheap->lock (); + } + inline void spawn_cygheap_unlock () + { + if (iscygwin ()) + cygheap->unlock (); + } }; extern child_info_spawn ch_spawn; diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index cb58b6eed..8ca19868a 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; + spawn_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; + spawn_cygheap_unlock (); __leave; } @@ -781,6 +783,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, if (get_errno () != ENOMEM) set_errno (EAGAIN); res = -1; + spawn_cygheap_unlock (); __leave; } child->dwProcessId = pi.dwProcessId; @@ -816,6 +819,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, CloseHandle (pi.hProcess); ForceCloseHandle (pi.hThread); res = -1; + spawn_cygheap_unlock (); __leave; } } @@ -844,6 +848,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; + spawn_cygheap_unlock (); switch (mode) { -- 2.45.1