casaroli opened a new pull request, #21530:
URL: https://github.com/apache/nuttx/pull/21530

   ## Summary
   
   `fdlist_copy()` gives the child of `fork()` or `vfork()` a copy of each 
descriptor without its flags, so `FD_CLOEXEC` is lost. POSIX says that the 
child inherits the descriptors with their flags. When the child then calls 
`exec()`, `exec()` closes nothing, and the new program has every descriptor 
that the parent marked close-on-exec. For example, a parent that waits for end 
of file on a close-on-exec pipe, to see that the child called `exec()`, waits 
until the new program ends.
   
   This PR keeps the close-on-exec flag of each descriptor in the copy for 
`fork()` and `vfork()`. The copies for `exec()`, `task_create()` and 
`posix_spawn()` do not change: they leave out the close-on-exec descriptors, as 
before.
   
   ## Impact
   
   Common code (`fs/inode/fs_files.c`), so all architectures and all build 
modes that have `fork()` or `vfork()`. A `fork()` or `vfork()` child now sees 
`FD_CLOEXEC` in `fcntl(F_GETFD)`, and `exec()` in the child closes these 
descriptors. A program that used a close-on-exec descriptor in the new program 
after `fork()` and `exec()` no longer gets it, as on other POSIX systems. No 
flat-build API change. No Documentation change: `Documentation/` does not 
describe the flags of a `fork()` child.
   
   ## Testing
   
   Test program, with a close-on-exec pipe and a plain pipe: `getfd`: in the 
child, `fcntl(F_GETFD)` has `FD_CLOEXEC` for the close-on-exec descriptor only. 
`eof`: the child calls `exec()`, and the parent must read end of file on the 
close-on-exec pipe at once, not after the 2 s that the new program runs. 
`exec`: the new program must not have the close-on-exec descriptor (`EBADF`), 
and it reports this through the plain pipe. The kernel builds use `fork()`; the 
flat and protected builds use `vfork()` and a builtin application. It is not in 
apps; a regression guard would need an apps PR.
   
   | Config | master 43f7f34b995 | this branch |
   |---|---|---|
   | `qemu-armv8a:nsh` (flat, `vfork()`), HVF | 3 failed; ostest status 0 | 0 
failed; ostest status 0 |
   | `qemu-armv8a:knsh` (kernel, `fork()`), HVF | 3 failed; ostest status 0 | 0 
failed; ostest status 0 |
   | `mps2-an500:knsh` (protected, `vfork()`), TCG | 3 failed; ostest status 0 
| 0 failed; ostest status 0 |
   | `rv-virt:knsh64` (kernel, `fork()`), TCG | 3 failed; ostest status 0 | 0 
failed; ostest status 0 |
   
   Master, the same in all:
   
   ```
   forkcloexec: getfd  FAIL (child exit 1)
   forkcloexec: eof    FAIL (read 0 after 2.0 s)
   forkcloexec: exec   FAIL (new program says 1, read 1)
   ```
   
   Options: `PIPES`, `LIBC_EXECFUNCS`, `SCHED_WAITPID`, `SCHED_HAVE_PARENT`, 
`SCHED_CHILD_STATUS`. `mps2-an500:knsh` also has `TLS_LOG2_MAXSTACK=15`, for 
the stack of the test. ostest has `fork()` and `vfork()` cases. Not run: 
`posix_spawn()` with file actions on a close-on-exec descriptor (the code path 
does not change), and `CONFIG_FDCLONE_STDIO`. Compilers: aarch64 GCC 14.2, 
arm-none-eabi GCC 15.3, RISC-V GCC 14.3.
   
   `tools/checkpatch.sh -c -u -m -g` passes.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to