digitalmars.D.bugs - [Issue 13258] New: std.process file closing logic is incorrect
- via Digitalmars-d-bugs (61/61) Aug 04 2014 https://issues.dlang.org/show_bug.cgi?id=13258
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 puremagic.com Reporter: thecybershadow 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. --
Aug 04 2014