On Sat, 23 Feb 2013 17:46:04 -0500, H. S. Teoh <hst...@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
<hst...@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

Reply via email to