[phobos] Major improvements to std.process

Lars Tandle Kyllingstad lars at kyllingen.net
Fri Mar 12 01:05:06 PST 2010


Steve Schveighoffer wrote:
> This looks great!

Thanks!


> Where would the Windows gui flag fit in?

Um...  I kinda forgot about that one. :)  What would you say is the most
common setting, and to which degree?

If we can assume that the user almost always wants it to be off, say, we
can just add a bool argument to the end of spawnProcess() that defaults
to false.

Since using a GUI is in most cases a design choice, another option is to 
make it a template parameter.  But that will require either of bugs 1820 
or 2972 to be fixed, otherwise every spawnProcess() call where you want 
to use its default value will looke like

    spawnProcess!()(...);


> Also, note that one can redirect both stdout and stderr to the same File, which means if you are closing both, you should only call close once on those files (I'm not sure how bad it is, but it probably will result in an ignored error from the OS).

Which close() operations are you referring to?

If it's the core.sys.posix.unistd.close() in the child process, I'm 
pretty sure nothing bad happens, except close() setting errno to EBADF 
and returning -1.  It probably good form to add the check, though.

If it's the std.stdio.File.close() in the parent process, then Andrei 
has designed it to be a no-op when the file is already closed.


> Another thing, I liked how the pid struct used to contain the pipes when I wanted to control the std handles, and how the spawnProcess function handled the pipe creation for me.  I wonder if it's possible to pass in a default argument for the handles, or have a separate function that does the pipe creation, and store the right ends of the pipe in the returned struct.
> 
> For example, if I want control over all three handles, I have to do:
> 
> auto lsstdin = Pipe.create();
> auto lsstdout = Pipe.create();
> auto lsstderr = Pipe.create();
> 
> auto lspid = spawnProcess("ls -l", lsstdin.readEnd, lsstdout.writeEnd, lsstderr.writeEnd);
> 
> If I do that a lot, I have a lot of pipes littering my local variables, and the code is very verbose.

But how often do you do that?  I mean, how often do you start several 
programs in a row, capturing all their input output streams, all inside 
one scope?

I'm asking out of curiosity.  I'm mostly a scientific programmer, not an 
application programmer, so maybe I'm not thinking big enough.  The 
reason I started working on this stuff was that I've been writing a 
Linux session manager -- just a lightweight one that takes care of 
starting other applications on login and restarting them if they die.  I 
can hardly imagine a program that needs to spawn more processes than 
that, but even that one contained just a single spawn command.

I think the current approach fits with the "systems programming 
language" aspect of D, and it will feel familiar to C programmers.  Only 
it will be a lot less bug-prone than the corresponding C code, because 
you no longer have to worry about manually closing the pipes, 
duplicating the right file descriptors, etc.


> I think we can build this on top of your function, into a struct/class that handles this stuff for you.  Or we could make the spawnProcess arguments variadic and put the created pipe handles back in the pid struct.

That's a possibility.  Something like this might do the trick:

   struct SlaveProcess
   {
       Pid pid;
       File stdin, stdout, stderr;
       this(string command, Redirect redirectFlags = Redirect.all);
       void spawn();
   }

I'm still not entirely convinced it is necessary, though.  :)

-Lars



> ----- Original Message ----
>> From: Lars Tandle Kyllingstad <lars at kyllingen.net>
>> To: Phobos mailing list <phobos at puremagic.com>
>> Sent: Thu, March 11, 2010 6:33:29 AM
>> Subject: [phobos] Major improvements to std.process
>>
>> I have just redone the interface of my std.process proposal, and I am very 
>> pleased with the result.
>>
>> Calling "ls -l" is now as simple as writing
>>
>>    spawnProcess("ls -l");
>>
>> while "ls -l | grep foobar > filesNamedFoobar.txt" isn't that big of a deal 
>> either:
>>
>>     auto pipe = Pipe.create();
>>     auto file = File("filesNamedFoobar.txt", "w");
>>
>>     auto lsPid = spawnProcess("ls -l", stdin, pipe.writeEnd);
>>     scope(exit) lsPid.wait();
>>
>>     auto grPid = spawnProcess("grep foobar", pipe.readEnd, file);
>>     scope(exit) grPid.wait();
>>
>> The documentation is also a lot better now (though the spawnProcess() signature 
>> looks horrible, but that's a DDoc issue).  As always, please check out
>>
>>     http://github.com/kyllingstad/ltk/blob/master/ltk/process.d
>>     http://kyllingen.net/code/ltk/doc/process.html
>>
>> and give me your opinions.
>>
>> -Lars
>>
>>
>> -- Lars Tandle Kyllingstad
>> @: lars at kyllingen.net
>> #: 40233221
>> w: http://www.kyllingen.net
>> _______________________________________________
>> phobos mailing list
>> phobos at puremagic.com
>> http://lists.puremagic.com/mailman/listinfo/phobos
> 
> 
> 
>       
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos


-- 
Lars Tandle Kyllingstad
@: lars at kyllingen.net
#: 40233221
w: http://www.kyllingen.net



More information about the phobos mailing list