[Issue 13258] New: std.process file closing logic is incorrect
via Digitalmars-d-bugs
digitalmars-d-bugs at puremagic.com
Mon Aug 4 23:03:03 PDT 2014
https://issues.dlang.org/show_bug.cgi?id=13258
Issue ID: 13258
Summary: std.process file closing logic is incorrect
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: Phobos
Assignee: nobody at puremagic.com
Reporter: thecybershadow at gmail.com
Consider a function in a library somewhere which runs a number of processes.
Example:
void fun()
{
import std.process;
spawnShell("echo foo").wait();
spawnShell("echo bar").wait();
}
Now, imagine that a consumer of this library function wants to redirect all
program output to a file, including that of subprocesses:
void main()
{
import std.stdio;
stdout.open("output.txt", "w");
// -- or --
//stdout = File("output.txt", "w");
fun();
}
This doesn't work, in a bad way.
On Windows, only "foo" is sent to "output.txt". "bar" will be sent to the
screen.
On Linux, the program will crash with "Attempting to call getFP() on an
unopened file".
This problem happens because there is a discrepancy in std.process' file
closing logic: the default stream arguments for new processes are
stdin/stdout/stderr - the variables in std.stdio, which can be repoened, and
thus can be different from the standard
STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO. However, when deciding whether to
close the streams or not, std.process compares the FDs with
STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO. Thus, it will close stdout if the
program had reopened it to a different file.
I can see these ways to solve this problem:
1. Make the default arguments be files which are actually the standard in/out
streams, i.e. the streams the program was started with. This has the problem in
that the example above will likely not do what the user intended.
2. Make std.process, by default, close the streams if they do not correspond to
std.stdio.stdin/stdout/stderr. Although this has the following problem: if a
program saves a copy of stdout, then overwrites std.stdio.stdout with something
that writes to a file, then creates a process and specifies the original stdout
as the output stream, then std.process will close it, which probably is not
what the user expected.
3. Make std.process, by default, close the streams if they are neither of the
STDIN_FILENO/STDOUT_FILENO/STDERR_FILENO, nor do they correspond to
std.stdio.stdin/stdout/stderr.
Option 3 looks like the sanest one, although the behavior is now a bit
uncomfortably complicated. In retrospect, I think all file closing should have
been explicit to avoid such problems.
--
More information about the Digitalmars-d-bugs
mailing list