...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/local_includes/cygheap.h | 2 ++
winsup/cygwin/mm/cygheap.cc | 22 +++++++++++++++++-----
winsup/cygwin/spawn.cc | 4 +++-
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/winsup/cygwin/local_includes/cygheap.h
b/winsup/cygwin/local_includes/cygheap.h
index fed87ec2b..aa928bc55 100644
--- a/winsup/cygwin/local_includes/cygheap.h
+++ b/winsup/cygwin/local_includes/cygheap.h
@@ -541,6 +541,8 @@ struct init_cygheap: public mini_cygheap
threadlist_t *find_tls (int, bool&);
sigset_t compute_sigblkmask ();
void unlock_tls (threadlist_t *t) { if (t) ReleaseMutex (t->mutex); }
+ void lock ();
+ void unlock ();
};
diff --git a/winsup/cygwin/mm/cygheap.cc b/winsup/cygwin/mm/cygheap.cc
index 338886468..2ed21e6ce 100644
--- a/winsup/cygwin/mm/cygheap.cc
+++ b/winsup/cygwin/mm/cygheap.cc
@@ -262,6 +262,18 @@ init_cygheap::init_installation_root ()
}
}
+void
+init_cygheap::lock ()
+{
+ AcquireSRWLockExclusive (&cygheap_protect);
+}
+
+void
+init_cygheap::unlock ()
+{
+ ReleaseSRWLockExclusive (&cygheap_protect);
+}
+
/* Initialize bucket_val. The value is the max size of a block
fitting into the bucket. The values are powers of two and their
medians: 32, 48, 64, 96, ...
@@ -367,7 +379,7 @@ _cmalloc (unsigned size)
if (b >= NBUCKETS)
return NULL;
- AcquireSRWLockExclusive (&cygheap_protect);
+ cygheap->lock ();
if (cygheap->buckets[b])
{
rvc = (_cmalloc_entry *) cygheap->buckets[b];
@@ -379,7 +391,7 @@ _cmalloc (unsigned size)
rvc = (_cmalloc_entry *) _csbrk (bucket_val[b] + sizeof
(_cmalloc_entry));
if (!rvc)
{
- ReleaseSRWLockExclusive (&cygheap_protect);
+ cygheap->unlock ();
return NULL;
}
@@ -387,19 +399,19 @@ _cmalloc (unsigned size)
rvc->prev = cygheap->chain;
cygheap->chain = rvc;
}
- ReleaseSRWLockExclusive (&cygheap_protect);
+ cygheap->unlock ();
return rvc->data;
}
static void
_cfree (void *ptr)
{
- AcquireSRWLockExclusive (&cygheap_protect);
+ cygheap->lock ();
_cmalloc_entry *rvc = to_cmalloc (ptr);
unsigned b = rvc->b;
rvc->ptr = cygheap->buckets[b];
cygheap->buckets[b] = (char *) rvc;
- ReleaseSRWLockExclusive (&cygheap_protect);
+ cygheap->unlock ();
}
static void *
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index cb58b6eed..fd623f4c5 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
@@ -844,6 +845,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)
{
--
2.45.1