system/popen: Avoid copying FILE#3511
Conversation
|
@nightt5879 it would be nice to have some test coverage to test it too. |
|
Thanks, I added a small The test opens two I verified the added test with:
The simulator run prints |
My bad, I looked only the first commit. So, everything is fine! |
Just to clarify: I added the additional commit after seeing your suggestion. |
Store the popen fd and shell pid in a fopencookie private cookie instead of embedding a copied FILE object in the popen container. The stream callbacks forward I/O to the pipe fd, and pclose() reads the shell pid from the stream cookie before fclose() closes the fd. Fixes apache#2937. Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
Add a small popen test that opens two read streams, verifies their output, and closes the first stream before the second. This covers reading from independent popen streams and pclose() handling for multiple concurrently opened popen streams. Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
23a698f to
9549d3b
Compare
Move popen stream cleanup into the fopencookie close callback so pclose() can close the stream directly. Also fix the invalid-mode error path, avoid closing the stream fd twice after fopencookie() takes ownership, and simplify the container free path. Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
|
@xiaoxiang781216 Thanks, I addressed the latest review comments in commit 6a16a4d. The follow-up changes:
One caveat I noticed while moving waitpid() into the fopencookie close callback: fclose() treats any non-OK close callback return as an EOF/error result. Because of that, popen_file_close() now returns OK after close() and waitpid() themselves succeed, and reports only close()/waitpid() failures as errors. Otherwise a normal nonzero shell termination status could be converted into an fclose() failure. I re-tested with:
|
Let close() and waitpid() leave errno directly on failure instead of saving and restoring it manually. Also document that fclose(stream) only closes retfd on the stream error path, so the child-side descriptors still need to be closed there. Signed-off-by: Nightt <87569709+nightt5879@users.noreply.github.com>
|
@nightt5879 please rebase your patch to fix the conflict, thanks. |
Summary
Fixes #2937.
system/popenwas embedding a copiedFILEobject in its private tracking container and copying it back inpclose(). That depends on libcFILElayout details.This PR makes
popen()return the actual stream fromfdopen()and keeps a small privateFILE * -> pidtracking list sopclose()can find the spawned shell process without copyingFILE.Scope:
popen()modes.pclose()responsible for closing the stream and waiting for the shell pid.EINVALifpclose()cannot find the stream in the private popen list.Impact
popen()/pclose()no longer rely on libcFILEinternals.Testing
Host:
sim:nshChecks:
git diff --check: passcheckpatch.sh -g HEAD~1..HEAD: passsim:nshbuild withCONFIG_SYSTEM_POPEN=yandCONFIG_EXAMPLES_POPEN=y: passCC: popen.cSIM elf with dynamic libs archive in nuttx.tgzprintf 'popen\npoweroff\n' | timeout 30s ./nuttx: passpopen("help")output is readpclose()