On Mon, Aug 02, 2021 at 12:33:30PM +0100, Mark Brown wrote:
On Mon, Aug 02, 2021 at 11:25:29AM +0100, Dave Martin wrote:
That's a reasonable position, but thinking about it a bit more, there's not really any loop at all here.
There definitely is an unwaited-for child and we don't pass WHONANG to wait(), so it will either return the child pid, or fail.
Without WUNTRACED or similar, the child must terminate to wake up the wait().
So is this just a matter of
pid = wait(&ret); if (pid == -1) { /* barf */ } assert(pid == child);
if (!WIFEXITED(ret)) { /* barf */ }
if (WEXITSTATUS(ret) != 0) { /* barf */ }
/* parse child's stdout etc. */
That really doesn't seem like a good idea - it's just asking for fragility if a signal gets delivered to the parent process or something. Even if almost all the time there will only be one trip through the loop we should still have the loop there for those few cases where it triggers.
This concern only applies when the program actually registers signal handlers.
wait() can't return for any other reason, and it mustn't, precisely because historically software would have made this assumption. This is one reason why wait3() etc. are separate functions.
That aside though, can't we use popen(3)?
I tend to forget about popen because it is "boring" to use it, but it looks like it fits this case quite well. Then it would be libc's problem how to fork and wait safely.
[...]
Cheers ---Dave