3 ms·
Now that's something I hadn't considered. Can you point me to some documentation?
by tekknolagi 9y ago
Now that's something I hadn't considered. Can you point me to some documentation?
- kd5bjo 9y agoUnfortunately, I don't know of a good write-up of how the kernel actually deals with file descriptors, aside from the man pages for the various syscalls you're using. From the kernel's perspective, there's nothing special about file descriptors 0, 1, and 2. The shell did the same pipe/fork/dup2/exec procedure as your code when it launched your program, and hooked the other end of the pipes to the terminal. When you call fork(), both processes keep all of their open file descriptors, which is why you have to close the ones you're not going to use with either close() or dup2(). If stdout or stderr is already attached to the correct destination when fork() is called, it's perfectly acceptable to leave them alone. Read-mode file descriptors (like stdin) are more problematic if they're used concurrently by multiple processes. Only one of the processes will read any given piece of data that was written into the pipe, so you need to coordinate the reads between the processes somehow.
- kd5bjo 9y agoActually, after looking at it again, I believe your code is at risk of deadlocking. If the program under test produces enough output to fill the stdout or stderr pipe buffer, the next write will block until your program reads some data out of it. That can only happen once you've finished writing everything to the stdin pipe, which may be full because the program under test has stopped reading from it (due to blocking on its write call). To avoid this, you need to process all three file descriptors in one loop using something like select() or poll() to work with whichever descriptor can make progress. Or, let a completely separate process (like the shell) handle the downstream file descriptors for you.