On Fri, 4 Jul 2025, Corinna Vinschen wrote:

> On Jul  3 12:03, Jeremy Drake via Cygwin-patches wrote:
> > On Thu, 3 Jul 2025, Jeremy Drake via Cygwin-patches wrote:
> > >
> > > https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_spawn_file_actions_addclose.html
> > >
> > > > A spawn file actions object, when passed to posix_spawn() or
> > > > posix_spawnp(), shall specify how the set of open file descriptors in
> > > > the calling process is transformed into a set of potentially open file
> > > > descriptors for the spawned process. This transformation shall be as if
> > > > the specified sequence of actions was performed exactly once, in the
> > > > context of the spawned process (prior to execution of the new process
> > > > image), in the order in which the actions were added to the object;
>
> I see what you mean.  The question of questions is if "as if" only
> covers the "performed exactly once" requirement, or if the "as if"
> really encompasses all three requirements, i.e.
>
> - as if the specified sequence of actions was performed exactly once
>
> - exactly in the context of the spawned process (prior to execution of the new
>   process image)
>
> - exactly in the order in which the actions were added to the object
>
> in contrast to
>
> - as if the specified sequence of actions was performed exactly once
>
> - as if in the context of the spawned process (prior to execution of the new
>   process image)
>
> - as if in the order in which the actions were added to the object
>
> My understanding (as a non-native speaker) is that "as if" only
> covers the "performed exactly once" requirement.  Applying "as if"
> to the order requirement doesn't make much sense to me.  And applying "as if"
> implicitely to the second requirement, but not to the third, doesn't
> make much sense to me either.

The "as if" performed exactly once doesn't make a whole lot of sense to me
either... To me, the only case where "as if" adds flexibility is the
context of the child process.

> On top of that you'd have the problem that the man pages of
> osix_spawn_file_actions_addclose and posix_spawn_file_actions_addchdir
> contradict each other.  This, of course, is always possible.  Only an
> RFC to the Austin Group could clarify this.  Maybe we should really do
> that.

The parts you quoted are in a section labeled "The following sections are
informative.".  But there does seem to be some confusion over whether the
actions *must* be performed in the child, or only *as if* they were
performed in the child.  Maybe they could clarify.  I interpreted the
posix_spawn rationale applying to the Windows model, whereas maybe they
only meant systems lacking fork due to their embedded-ness (lacking mmu
etc).  I don't see why they would preclude this though.  I'm kind of
considering the Cygwin dll as the "kernel" in this context.

> > > > How do you run, say,
> > > >
> > > >   addopen (42, "dir", O_SEARCH|O_DIRECTORY)
> > > >
> > > > without potentially disrupting the actions of another parallel thread,
> > > > just reading data from a file attached to fd 42?
> > >
> > > First, I wouldn't be rushing to optimize the case of file descriptors
> > > greater than 2, because I don't see that as a common case.  However, if
> > > necessary, I'd do it much the same way as for 0 through 2:
> > >
> > > hold the lock_process lock
> > > perform the open, and assign the returned file descriptor into a mapping
> > > of file descriptors for the child.
> > > for a Win32 child, implement the lpReserved2 used by msvcrt to specify
> > > the fd to handle mapping
> > > for a Cygwin child, change the stdin/stdout/stderr child_info_spawn to
> > > some mapping structure for move_fd operations to perform in handle_spawn.
> >
> > I get the idea that "some mapping structure" in child_info_spawn could
> > just be the file actions and attributes from posix_spawn, and instead of
> > move_fd process the actions and attributes in handle_spawn.  Why I am
> > resisting this is that I don't want to have to do this twice: once in the
> > parent as I do now, which must continue to exist for win32 processes AND
> > to find the directory to which a relative program path is relative; and do
> > it again during Cygwin process startup.  I'm really struggling to see why
> > the added complexity of a special path for Cygwin children is necessary
> > here.
>
> Yeah, ok, I get that.  I understand that you're frustrated.  Please keep
> in mind that, to me, Cygwin processes are the first class citizens,
> native processes are second class.  Therefore it would be great to be
> able to do it right for Cygwin processes in the first place.
>
> I'm not trying to be unreasonable and inclined to go with your patchset
> for a start.  But, to me, considering the Issue 8 descriptions, it
> seems we could do more, better for Cygwin processes.
>
> Or maybe not!  But that will probably require more tedious discussions
> like this one and throwing ideas back and forth.  It would be a bit
> disappointing to be stuck with this and not trying to come up with
> funny ideas to workaround obstacles like O_CLOEXEC, POSIX_SPAWN_RESETIDS,
> etc.

I'm sorry if I'm sounding frustrated.  I am just trying to debate to find
the best implementation.  I think that having two versions of processing
the file actions is asking for inconsistencies and bugs.  As you point
out, non-Cygwin processes are second-class citizens to Cygwin but are more
important to MSYS2 and Git for Windows, so I can see bugs in the
non-Cygwin case going undiscovered until after a Cygwin release, when
MSYS2 and Git for Windows try to integrate it and exercise the case of a
Cygwin GNU make running mingw gcc, or Cygwin bash running mingw git
running Cygwin ssh, or any other bizarre combination.

I'd be happy to consider a counter implementation.  I think this would
have to:
1. exist inside child_info_spawn::worker, because path_conv.iscygexec ()
wouldn't be reliable until after av::setup has run and set it based in
hook_or_detect_cygwin.
2. process the file actions in the parent to compute the child's cwd, so
that a relative program is found relative to the correct cwd.  This has
a certain amount of chicken-and-egg because av::setup needs to use this
cwd to find relative paths in the #! at least.
3. the malloc/strdup/free in newlib posix_spawn.c needs to be swapped out
for cmalloc-based ones so the structures remain available in the child.
4. the posix_spawnattrs_t and posix_spawn_file_actions_t need to be passed
to the child (child_info_spawn or the moreinfo member)
5. the process_spawnattr and process_file_actions in newlib posix_spawn.c
need to be called from dcrt0.c (probably handle_spawn).



Reply via email to