[phobos] Major improvements to std.process
Steve Schveighoffer
schveiguy at yahoo.com
Fri Mar 12 05:51:22 PST 2010
----- Original Message ----
> From: Lars Tandle Kyllingstad <lars at kyllingen.net>
>
> Steve Schveighoffer wrote:
> > 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?
It depends on whether you want a console or not. I think the default should be unset, because that mimics the default for Linux. Plus I think it's the default (no flags) in windows.
> 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.
That sounds fine to me. We could also possibly remove that argument unless the version is windows. But we can leave it in as a noop for portability.
> 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!()(...);
No :)
> > 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.
I was thinking of the parent. It's probably fine in that case.
> > 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?
In the case where I used Tango's Process object, I redirected all three for all processes, because I was sending the results via a custom network protocol to a server. The default option in Tango was to redirect all three to pipes contained in the instance. If you are not writing a shell, I think this is a very common situation (wanting control over all three standard handles).
> 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.
It's just that the creation of the pipes and creation of the process always go hand in hand, you very seldom want to separate those functions. It's somewhat of a nuisance to write many times "create this pipe, now this one, then create the process that uses them". It would be much nicer to just say "create the process, use pipes for these handles, and give me everything back when you're done." I liken it to how constructors unify the process of creation and initialization in one line. Yes, you can split them, but why?
I'm not saying there isn't use for your signatures, I agree having fine-grained control over which file descriptors are used is a good thing. I just think we should cater to common cases, even if it's via wrapper functions/structs.
-Steve
More information about the phobos
mailing list