JEP 102 Process Updates revised API draft
Roger Riggs
Roger.Riggs at Oracle.com
Tue Feb 10 19:52:49 UTC 2015
Hi Peter,
Yep, I hadn't gotten to improving that part of the implementation yet.
The threading needs to be revised; System threads and the limited stack
were used currently
to monitor processes (on Linux) but are not suitable for evaluating
CompletionStages.
Switching to some form of Executor as a source of thread is needed.
I was also trying to preserve an option to have a lightweight monitor
of thread liveness that did not require a thread to improve scalability.
That would allow the thread needed for CompletionStage to be created
only if and
when it is needed.
On 2/10/2015 1:17 PM, Peter Levart wrote:
> On 02/10/2015 02:02 PM, Peter Levart wrote:
>> On 02/10/2015 12:35 PM, Peter Levart wrote:
>>> 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. 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?).
>>>
>>> - ProcessHandle.completableFuture().cancel(true/false) just cancels
>>> the CompletableFuture and does not do anything to the process itself.
>>>
>>> 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?
>>
>> Contemplating on this a little more, then perhaps the singleton-per
>> pid CompletionStage could be OK if it was a "mirror" of real process
>> state. For that purpose then, instead of .completableFuture() the
>> method would be:
>>
>> public CompletionStage<ProcessHandle> completionStage()
>>
>> Returns a CompletionStage<ProcessHandle> for the process. The
>> CompletionStage provides supporting dependent functions and actions
>> that are run upon process completion.
>>
>> Returns:
>> a CompletionStage<ProcessHandle> for the ProcessHandle; the same
>> instance is returned for each unique pid.
>>
>>
>> This would provide the most clean API I think, as CompletionStage
>> does not have any cancel(), complete(), obtrudeXXX() or get()
>> methods. One could still obtain a CompletableFuture by calling
>> .toCompletableFuture() on the CompletionStage, but that future would
>> be a 2nd stage future (like calling .thenApply(x -> x)) which would
>> not propagate cancel(true) to the process destruction.
>>
>> The implementation could still use CompletableFuture under the hood,
>> but exposed wrapped in a delegating CompletionStage proxy.
>>
>> So the javadoc might be written as:
>>
>>
>> public abstract void destroy()
>>
>> Kills the process. Whether the process represented by this Process
>> object is forcibly terminated or not is implementation dependent. If
>> the process is not alive, no action is taken.
>>
>> If/when the process dies as the result of calling destroy(), the
>> completionStage() completes exceptionally with CompletionException,
>> wrapping ProcessDestroyedException.
>>
>>
>> public abstract ProcessHandle destroyForcibly()
>>
>> Kills the process. The process represented by this ProcessHandle
>> object is forcibly terminated. If the process is not alive, no action
>> is taken.
>>
>> If/when the process dies as the result of calling destroyForcibly(),
>> the completionStage() completes exceptionally with
>> CompletionException, wrapping ProcessDestroyedException.
>>
>>
>> But I'm still unsure of whether it would be better for the
>> completionStage() to complete normally in any case. Unless the fact
>> that the process died as a result of killing it could be reliably
>> communicated regardless of who was responsible for the killing
>> (either via ProcessHandle.destoroy() or by a KILL/TERMINATE signal
>> originating from outside the VM).
>>
>> Peter
>>
>>
>
> Hi Roger,
>
> I checked out your branch in jdk9-sandbox and studied current
> implementation.
>
> One problem with this approach (returning a singleton-per-pid
> CompletableFuture or CompletionStage) is that current
> processReaperExecutor is using threads with very small stack size (32
> K) and the returned CompletableFuture could be instructed to append a
> continuation that executes synchronously:
>
> CompletionStage.thenApply(), CompletionStage.handle(), etc...
>
> ... so user code would execute by such thread and probably get
> StackOverflowException...
Yes, a normal stack size is needed.
>
> Also, multiple ProcessHandle objects together with a Process object
> for the same pid each return a separate CompletableFuture instance
> (not what spec. says). Each of them also spawns it's own thread to
> wait for process termination.
>
> Here's a better approach (a diff to your branch):
>
> http://cr.openjdk.java.net/~plevart/jdk9-sandbox/JDK-8046092-branch/webrev.01/
>
>
> ...it contains a global registry of internal CompletionStage(s) - one
> per pid. They are not exposed to users, just used internally (in Unix
> ProcessImpl) to execute cleanup and in .completionStage() to append an
> asynchronous stage which is returned by the method on each call. So
> users appending synchronous continuations to returned CompletionStage
> would execute them in a common FJ pool.
Yep that's the idea and should be common across Windows/Unix/MacOSx and
usable with Process and ProcessHandles. I'll take another look.
Thanks, Roger
>
> I haven't tested this yet. It's just an idea to share.
>
> Regards, Peter
>
>
More information about the core-libs-dev
mailing list