Hi Peter,

On 2/10/2015 6:35 AM, Peter Levart wrote:
On 02/10/2015 12:25 AM, Roger Riggs wrote:
Hi,

After a protracted absence from working on JEP 102, the updated API draft provides access to process hierarchies and individual process information; as permitted by the OS. The relationship between Process and ProcessHandle
is clarified and the security model validated.

Both Processes and ProcessHandles can be monitored using CompletableFuture
for termination and to trigger additional actions on Process exit.
Information about processes includes the total cputime, starttime, user,
executable, and arguments.

Please review and comment:
   http://cr.openjdk.java.net/~rriggs/ph-apidraft/

Thanks, Roger




Hi Roger,

Great to see progress on this.

Here are my comments:

ProcessHandle.{allProcesses,allChildren,children} return Stream<ProcessHandle>. This is convenient if one wants to use Stream API, but a little more inconvenient and perhaps with additional overhead if one doesn't. Since all those methods return a "snapshot", I can imagine that internally, there is a collection built from this snapshot. So it would be most appropriate to return a List<ProcessHandle>. One can always continue the expression by appending .stream()..., but on the other hand if one wants to .collect(toList()), additional copying is introduced.
I've been pulled both ways by various folks here also.
Both Streams and Collections are easily converted to the other.
The internal snapshot is an array of int pid's; with the Stream, the creation of ProcessHandles can
be delayed until they are needed, if they are needed.

ProcessHandle.completableFuture().cancel(true) forcibly destorys (destroyForcibly()) the process *and* vice versa: destory[Forcibly]() cancels the CompletableFuture. I don't know if this is the best way - can't decide yet. In particular, in the implementation it would be hard to achieve the atommicity of both destroying the process and canceling the future. Races are inevitable.
Atomicity is provided by CompletableFuture, it handles the atomicity of updating its state. If cancelled, there is no useful information or synchronization is needed from the (dieing) Process;
the CompletableFuture state/status is cancelled.
So it would be better to think of a process (and a ProcessHandle representing it) as the 1st stage in the processing pipeline, where ProcessHandle.completableFuture() is it's dependent stage which tracks real changes of the process. Which means the behaviour would be something like the following:

- ProcessHandle.destroy[Forcibly]() triggers destruction of the process which in turn (when successful) triggers completion of CompletableFuture, exceptionally with CompletionException, wrapping the exception indicating the destruction of the process (ProcessDestroyedException?).
Maybe thinking along the similar lines; Process and Future are loosely coupled; A process exiting, regardless of whether it was killed by some entity in the system
or the Java API should complete the Future.
For a Process, the exitStatus is available and could be used to modify the normal vs exceptional completion. But for an arbitrary ProcessHandle, the process may not have been spawned by this process; in that case the exit status is not available (see previous long discussions about reaping). Also, the exit status may not be a reliable indication of success vs failure of the process. So the best that can be reported is that the Process is terminated and the Future is completed (normally).


- ProcessHandle.completableFuture().cancel(true/false) just cancels the CompletableFuture and does not do anything to the process itself.

My model was that the CompletableFuture from ProcessHandle is a proxy for the process itself. It is an abstraction for the Process that is independent of the implementation (as a Process).
It looks just like any other stage in the tree of CompletionStages.
The application that spawns the Process can control what it exposes as the CompletableFuture it can expose the root or create another Completable future to hang other operations on.


In that variant, then perhaps it would be more appropriate for ProcessHandle.completableFuture() to be a "factory" for CompletableFuture(s) so that each call would return new independent instance.

What do you think?

I'm not sure which model is more useful to the application/library.
The implementation may be simpler if it only has to keep track of a single CompletableFuture
instead of a set but decoupling may be simpler to model.

Thanks, Roger

Regards, Peter


Reply via email to