rust-lang/rust — pull request #16407 by ipetkov (2014-08-10 22:12:56+00:00)
Title: libnative: process spawning should not close inherited file descriptors

When creating a subprocess via `std::io::process::Command` it is possible to allow the child to inherit certain open file descriptors. When the process is spawned (in `native::io::process`), however, the file descriptor is unconditionally closed. This is an error for the following reasons:

1. The caller can safely create a file descriptor via `native::io::file::open`, which returns a `FileDesc` on success. Since there is no public interface for specifying that the internal fd should NOT be cleaned up, the `FileDesc` structure will attempt to close the fd when it is destroyed. Since spawning closes the file descriptor, when the `FileDesc` structure mentioned above goes out of scope, it will print an error message to screen. This behavior may be unwanted, and there is no way to prevent it without leaking the `FileDesc` structure (which is not a good alternative).

2. Alternatively, it is possible for another file to be opened whose fd matches that stored by the `FileDesc` structure returned by `native::io::file::open` before said structure goes out of scope. Thus when it does, it will *incorrectly* succeed at closing the file, causing unexpected errors for the task that opened the file.

3. The caller may not wish to close the file descriptor just yet. Imagine a scenario where a lock file is created by a child process and unlinked when it exits. The parent may wish to keep the file on disk until it exits so that any other process looking for that lock file will see it. When it finally does exit and close its handle to the file, the OS will clean it up then.

Thus the caller must be solely responsible for cleaning up (or leaking if so desired) any opened file descriptors, especially since the `std::io::process:Command` interface for adding inherited file descriptors involves using a literal descriptor and not a wrapper like `FileDesc`.