[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