The new std.process is ready for review

Steven Schveighoffer schveiguy at yahoo.com
Sat Feb 23 15:55:19 PST 2013


On Sat, 23 Feb 2013 17:46:04 -0500, H. S. Teoh <hsteoh at quickfur.ath.cx>  
wrote:

> On Sat, Feb 23, 2013 at 03:15:26PM -0500, Steven Schveighoffer wrote:
>> On Sat, 23 Feb 2013 11:42:26 -0500, H. S. Teoh
>> <hsteoh at quickfur.ath.cx> wrote:
>>
>> >- wait():
>> >   - Some code examples would be nice.
>> >
>> >   - For the POSIX-specific version, I thought the Posix standard
>> >     specifies that the actual return code / signal number should be
>> >     extracted by means of system-specific macros (in C anyway)?
>> >     Wouldn't it be better to encapsulate this in a POD struct or
>> >     something instead of exposing the implementation-specific values
>> >     to the user?
>>
>> We handle the extraction as an implementation detail, the result
>> should be cross-platform (at least on signal-using platforms).  I
>> don't know what a POD struct would get you, maybe you could elaborate
>> what you mean?
>
> Oh, I thought the return value was just straight from the syscall, which
> requires WIFEXITED, WEXITSTATUS, WCOREDUMP, etc., to interpret. If it
> has already been suitably interpreted in std.process, then I guess it's
> OK.

I think that's the case. (double checking) yes.

>
> Otherwise, I was thinking of encapsulating these macros in some kind of
> POD struct, that provides methods like .ifExited, .exitStatus,
> .coreDump, etc. so that the user code doesn't have to directly play with
> the exact values returned by the specific OS.

All we look at is WIFEXITED and WIFSIGNALED.  I think the others are Linux  
specific.  I don't think std.process2 should expose all the vagaries of  
the OS it's on, this is a cross-platform library.  Doing signals was easy  
because we embedded it in the int.

There is always pid.osHandle, which you can use to do whatever you want.

>> >   - How do I wait for *any* child process to terminate, not just a
>> >     specific Pid?
>>
>> I don't think we have a method to do that.  It would be complex,
>> especially if posix wait() returned a pid that we are not handling!
>>
>> I suppose what you could do is call posix wait (I have a feeling we
>> may need to change our global wait function, or eliminate it), and
>> then map the result back to a Pid you are tracking.
>>
>> You have any ideas how this could be implemented?  I'd prefer not to
>> keep a global cache of child process objects...
>
> Why not?  On Posix at least, you get SIGCHLD, etc., for all child
> processes anyway, so a global cache doesn't seem to be out-of-place.
>
> But you do have a point about pids that we aren't managing, e.g. if the
> user code is doing some fork()s on its own. But the way I see it,
> std.process is supposed to alleviate the need to do such things
> directly, so in my mind, if everything is going through std.process
> anyway, might as well just manage all child processes there. OTOH, this
> may cause problems if the D program links in C/C++ libraries that manage
> their own child processes.

Well, there is always the possibility of a child creating a child, and  
exiting, the grandchild then becomes our child.  There is no way to  
predict or plan for that.

If we expose the general wait call, then we will be subject to odd cases,  
and I think at that point, it's a specialized application.  We provide a  
way to get back to OS-specific land via osHandle.

> Still, it would be nice to have some way of waiting for a set of child
> Pids, not just a single one. It would be a pain if user code had to
> manually manage child processes all the time when there's more than one
> of them running at a time.

This is not possible on Linux/OSX (you can't specify the process subset to  
wait for), but possible on Windows.  We chose not to expose that because  
it's very application specific, and we are trying to write a cross  
platform library.

You can always write a function that does this.  Simple example:

Pid[int] processes;
// create processes, storing them by OS pid
int pid;
while(pid = .wait())
{
    Pid *p = processes[pid];
    if(p)
    {
       // handle child exiting
    }
}

> Hmm. The more I think about it, the more it makes sense to just have
> std.process manage all child process related stuff. It's too painful to
> deal with multiple child processes otherwise. Maybe provide an opt-out
> in case you need to link in some C/C++ libraries that need their own
> child process handling, but the default, IMO, should be to manage
> everything through std.process.

I can imagine that a ProcessManager singleton class could be written that  
collects all exited children, and does anything you need.  But I don't  
know if it's a necessary component for std.process to go out the door.  We  
currently have no such feature, so I would push for std.process to be  
reviewed and accepted without that, and then consider that an enhancement  
request.

Now, one thing we could probably do quickly and easily is add a wait  
function that returns immediately if the process is not done.  I'm pretty  
sure that is supported on all platforms.

-Steve


More information about the Digitalmars-d mailing list