Redirecting Stdio is Hard
blog.httrack.com
blog.httrack.com
# Sanitize std{in,out,err} because they'll be shared with untrusted child
# processes (http://crbug.com/376567).
exec < /dev/null
exec > >(exec cat)
exec 2> >(exec cat >&2)
Somehow child processes can abuse stdin/stderr/stdout in ... creative ways?I'm wondering why these launchers differ so much.
It would be nice to have more detail here, at least why this is "historical" and "unfortunate". A whole slew of programs wouldn't be possible and capabilities wouldn't exist without this, both older and modern. Two examples are inetd's wait functionality (letting the spawned program accept(2) further connections on the inherited listening socket) and systemd's, ahem, socket activation.
main program sens[sic] commands to remote location and closes the socket
If you intend the socket connection to be ended, you should be calling shutdown(2) on it, not close(2). close(2) only asserts that the calling process is done with it. The child process would end up with a dead socket fd (although, there are bugs related to improperly handling this, here's one that bit me: https://github.com/brianmario/mysql2/issues/516 ). This is why the failure cases on syscalls should always be examined and there should be a sane, default failure case. In an ideal world, the leaked file descriptor would merely be just that, and a properly written program would ignore (or close) any file descriptors it wasn't explicitly designed/meant to use.
I think a lot of people feel that way about Unix features that interact awkwardly with threads. I tend to feel that threads are the unfortunate part, but that seems to be minority opinion.
I read that as "it would be better if the default for spawned processes were to _not_ share file descriptors", not as "it would be better if it were impossible to inherit file descriptors"
We got a bug report that if you ran a program that used the library by doing:
prog >& /tmp/log
then stderr from the program before my library started logging would disappear. If you did this intead, it would work fine: prog |& tee /tmp/log
It turned out (obvious in hindsight, not at the time) that we opened /dev/stderr with O_TRUNC, causing /tmp/log to be truncated and earlier logs to be lost.TLDR: /dev/stderr can be truncated, which was unexpected.
Is there a saner way to facilitate this than what I have done? Which is to run it like this from the shell:
something | mycmd 10<&1
and in mycmd read stdin as normal and interactive input from /dev/fd/10