The new std.process is ready for review
Lars T. Kyllingstad
public at kyllingen.net
Sat Mar 9 10:44:44 PST 2013
On Saturday, 9 March 2013 at 18:35:25 UTC, Steven Schveighoffer
wrote:
> On Sat, 09 Mar 2013 11:05:14 -0500, Lars T. Kyllingstad
> <public at kyllingen.net> wrote:
>
>> On Wednesday, 6 March 2013 at 16:45:51 UTC, Steven
>> Schveighoffer wrote:
>>> On Tue, 05 Mar 2013 17:38:09 -0500, Vladimir Panteleev
>>> <vladimir at thecybershadow.net> wrote:
>>
>>>> I've also initially tried writing a different program:
>>>>
>>>> [...]
>>>
>>> Linux should work here. From what I can tell, you are doing
>>> it right.
>>>
>>> If I get some time, I'll try and debug this.
>>
>> I think I know what the problem is, and it sucks bigtime. :(
>>
>> Since the child process inherits the parent's open file
>> descriptors, both ends of a pipe will be open in the child
>> process. We have separated pipe creation and process
>> creation, so spawnProcess() knows nothing about the "other"
>> end of the pipe it receives, and is therefore unable to close
>> it.
>>
>> In this particular case, the problem is that "sort" doesn't do
>> anything until it receives EOF on standard input, which never
>> happens, because even though the write end of the pipe is
>> closed in the parent process, it is still open in the child.
>
> Oh crap, that is bad.
>
> Unlike Windows which is an opt-in strategy, unix has an opt-out
> strategy (there is the F_CLOEXEC flag). For consistency, I
> think it would be good to close all the file descriptors before
> calling exec.
>
>> I don't know how to solve this in a good way. I can think of
>> a few alternatives, and they all suck:
>>
>> 1. Make a "special" spawnProcess() function for pipe
>> redirection.
>> 2. Use the "process object" approach, like Tango and Qt.
>> 3. After fork(), in the child process, loop over the full
>> range of possible file descriptors and close the ones we don't
>> want open.
>>
>> The last one would let us keep the current API (and would have
>> the added benefit of cleaning up unused FDs) but I have no
>> idea how it would impact performance.
>
> I think 3 is the correct answer, it is consistent with Windows,
> and the most logical behavior. For instance, if other threads
> are open and doing other things that aren't related (like
> network sockets), those too will be inherited! We should close
> all file descriptors.
I think so too. In C, you have to know about these things, and
they are specified in the documentation for fork() and exec().
In D you shouldn't have to know, things should "just work" the
way you expect them to.
> How do you loop over all open ones? Just curious :)
You don't. That is why I said solution (3) sucks too. :) You
have to loop over all possible non-std file descriptors, i.e.
from 3 to the maximum number of open files. (On my Ubuntu
installation, this is by default 1024, but may be as much as
4096. I don't know about other *NIXes)
Here is how to do it:
import core.sys.posix.unistd, core.sys.posix.sys.resource;
rlimit r;
getrlimit(RLIMIT_NOFILE, &r);
for (int i = 0; i < r.rlim_cur; ++i)
close(i);
Lars
More information about the Digitalmars-d
mailing list