On Tue, 22 Jul 2025 10:40:50 +0200
Corinna Vinschen wrote:
> Hi Takashi,
> 
> On Jul 22 09:31, Takashi Yano wrote:
> > ...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>
> > ---
> 
> When you create a new patch version, it would be nice if you could
> add version info after the three dashes, kind of like
> 
>   v3: add cygheap_init::lock method
>   v4: inline cygheap_init::lock method
>   v5: don't lock cygheap for non-cygwin child
>   v6: add spawn_cygheap_lock
> 
> Otherwise it's a bit tricky to review because one has to first find
> out why a new version exists at all.
> 
> >  winsup/cygwin/spawn.cc | 12 +++++++++++-
> >  1 file changed, 11 insertions(+), 1 deletion(-)
> > 
> > diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
> > index cb58b6eed..cf344d382 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,9 @@ child_info_spawn::worker (const char *prog_arg, const 
> > char *const *argv,
> >  
> >        cygpid = (mode != _P_OVERLAY) ? create_cygwin_pid () : myself->pid;
> >  
> > +      if (iscygwin ())
> > +   cygheap->lock ();
> > +      refresh_cygheap ();
> 
> I compared v5 and v6, and I think we should not introduce the
> spawn_cygheap_lock() method.  It hides a crucial problem.
> 
> Assuming no further change, I'd prefer v5, BUT with a comment preceeding
> the `if (iscygwin ())' condition, along the lines of
> 
>    /* Lock the cygheap here to make sure the child doesn't copy a
>       cygheap while it's being modified in parallel.  Don't lock if
>       the child is a non-Cygwin child to avoid a deadlock in
>       close_all_files(). */
> 
> However, IIUC this situation only occurs if a non-Cygwin child is
> execve'd, and we're talking about the close_all_files() call in line 768
> in origin/main, which potentially occurs while the cygheap would be
> locked by your patch, right?
> 
> I see two different ways out:
> 
> - Either convert the SRWLOCK to a muto to allow a recursive cygheap lock.
> 
> - Or move the close_all_files() call.
> 
> The latter seems to me like the way to go here.
> 
> The close_all_files() call was introduced by commit 2f415d5efae5a
> ("Cygwin: pty: Disable FreeConsole() on close for non cygwin process.")
> 
> Why not move it out of the locked region?

Thanks for the advice. I'll apply your idea and submit v7 patch.
-- 
Takashi Yano <takashi.y...@nifty.ne.jp>

Reply via email to