...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.

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:
Signed-off-by: Takashi Yano <[email protected]>
---
 winsup/cygwin/mm/cygheap.cc | 2 +-
 winsup/cygwin/spawn.cc      | 5 ++++-
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/winsup/cygwin/mm/cygheap.cc b/winsup/cygwin/mm/cygheap.cc
index 338886468..b3ebca5d6 100644
--- a/winsup/cygwin/mm/cygheap.cc
+++ b/winsup/cygwin/mm/cygheap.cc
@@ -35,7 +35,7 @@ static mini_cygheap NO_COPY cygheap_dummy =
 init_cygheap NO_COPY *cygheap = (init_cygheap *) &cygheap_dummy;
 void NO_COPY *cygheap_max;
 
-static NO_COPY SRWLOCK cygheap_protect = SRWLOCK_INIT;
+NO_COPY SRWLOCK cygheap_protect = SRWLOCK_INIT;
 
 struct cygheap_entry
 {
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index cb58b6eed..a4c2b0549 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -273,6 +273,7 @@ struct system_call_handle
 };
 
 child_info_spawn NO_COPY ch_spawn;
+extern SRWLOCK cygheap_protect;
 
 extern "C" void __posix_spawn_sem_release (void *sem, int error);
 
@@ -542,7 +543,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 +611,8 @@ child_info_spawn::worker (const char *prog_arg, const char 
*const *argv,
 
       cygpid = (mode != _P_OVERLAY) ? create_cygwin_pid () : myself->pid;
 
+      AcquireSRWLockExclusive (&cygheap_protect);
+      refresh_cygheap ();
       wchar_t wcmd[(size_t) cmd];
       if (!::cygheap->user.issetuid ()
          || (::cygheap->user.saved_uid == ::cygheap->user.real_uid
@@ -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;
+      ReleaseSRWLockExclusive (&cygheap_protect);
 
       switch (mode)
        {
-- 
2.45.1

Reply via email to