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