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. |
| ****************************************************************************/ | ||
|
|
||
| static sem_t g_popen_sem = SEM_INITIALIZER(1); | ||
| static FAR struct popen_file_s *g_popen_files; |
There was a problem hiding this comment.
but it isn't good (or even worse) to add a global list to fix a minor issue.
There was a problem hiding this comment.
Thanks for the review. I trust your judgment here.
The global list was added because once popen() returns the real fdopen() stream, pclose(FILE *stream) still needs a way to recover the shell pid for waitpid().
The alternatives I can see are:
- keep external
stream/fd -> pidstate, as this PR does; - store popen metadata in NuttX
FILE/stdio internals; - keep the old copied-
FILEapproach; - make a broader libc/helper API change.
I chose (1) to avoid copying FILE or modifying libc internals, but I understand this may not be the tradeoff you want for this issue.
What approach would you suggest here?
There was a problem hiding this comment.
@michallenc added fopencookie before, you may attach the private data to FILE by this function:
https://github.com/apache/nuttx/pulls?q=fopencookie
There was a problem hiding this comment.
Thanks for the pointer. I followed this direction and reworked the implementation to use fopencookie(): popen now stores the pipe fd and shell pid in the stream's private cookie instead of a global FILE-to-pid list. The cookie callbacks forward read/write/close to the fd, and pclose() retrieves the pid from the cookie before fclose()/waitpid(). The popen test remains in the second commit and passes on sim:nsh.
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
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()