RFR 9: 8077350 Process API Updates Implementation Review

Peter Levart peter.levart at gmail.com
Fri Apr 17 08:05:35 UTC 2015


Hi Roger,

Retrieving and caching the process start time as soon as ProcessHandle 
is instantiated might be a good idea. "destroy" native code would then 
use pid *and* start time to check the identity of the process before 
killing it.

At least on Linux (/proc/<pid>/stat) and Solaris (/proc/<pid>/status) it 
is not necessary to open those special files and read them. Just doing 
stat() on them and using the st_mtime will get you the process start 
time. I see AIX shares native code with Linux (unix), so perhaps AIX 
does the same. Mac OSX and Windows have special calls...

In case OS does not allow retrieving the start time (not owner or 
similar), it should be cached as some "undefined" value and treated the 
same when destroying. If while obtaining the ProcessHandle *and* while 
destorying the process, the start time of the process with a particular 
pid is "undefined" then there are two options:

1 - don't kill the process
2 - kill the process

They might actually be no different as the reason of not being able to 
retrieve the start time (not owner) might prevent the process from being 
killed too, so option 2 could be used to allow killing on any 
hypothetical platforms that don't support retrieving start time and it 
is no worse than current implementation anyway.

What do you think?

Regards, Peter

On 04/11/2015 08:55 PM, Roger Riggs wrote:
> Hi Thomas,
>
> Thanks for the comments.
>
> On 4/11/2015 8:31 AM, Thomas Stüfe wrote:
>> Hi Roger,
>>
>> I have a question about getChildren() and getAllChildren().
>>
>> I assume the point of those functions is to implement point 4 of JEP 
>> 102 ("The ability to deal with process trees, in particular some 
>> means to destroy a process tree."), by returning a collection of PIDs 
>> which are the children of the process and then killing them?
> Earlier versions included a killProcess tree method but it was 
> recommended to leave
> the exact algorithm to kill processes to the caller.
>>
>> However, I am not sure that this can be implemented in a safe way, at 
>> least on UNIX, because - as Martin already pointed out - of PID 
>> recycling. I do not see how you can prevent allChildren() from 
>> returning PIDs which may be already reaped and recyled when you use 
>> them later. How do you prevent that?
> Unless there is an extended time between getting the children and 
> destroying them the pids will still be valid.
> The technique of caching the start time can prevent that case; though 
> it has AFAIK not been a problem.
>>
>> Note even if your coding is bulletproof, that allChildren() will also 
>> return PIDs of sub processes which are completely unrelated to you 
>> and Process.java - they could have been forked by some third party 
>> native code which just happens to run in parallel in the same 
>> process. There, you have no control about when it gets reaped. It 
>> might already have been reaped by the time allChildren() returns, and 
>> now the same PID got recycled as another, unrelated process.
> Of course, the best case is for an application to spawn and manage its 
> own processes
> and handle there proper termination.
> The use cases for children/allChildren are focused on 
> supervisory/executive functions
> that monitor a running system and can cleanup even in the case of 
> unexpected failures.
> All management of processes is subject to OS limitations, if the PID 
> were from a completely
> different process tree, the ordinary destroy/info functions would not 
> be available
> unless the process was running as a privileged os user (same as any 
> other native application).
>
>>
>> If I am right, it would not be sufficient to state "There is no 
>> guarantee that a process is alive." - it may be alive but by now be a 
>> different process altogether. This makes "allChildren()" useless for 
>> many cases, because the returned information may already be obsolete 
>> the moment the function returns.
> The caching of startTime can remove the ambiguity.
>>
>> Of course I may something missing here?
>>
>> But if I got all that right and the sole purpose of allChildren() is 
>> to be able to kill them (or otherwise signal them), why not use 
>> process groups? Process groups would be the traditional way on POSIX 
>> platforms to handle process trees, and they are also available on 
>> Windows in the form of Job Objects.
>>
>> Using process groups to signal sub process trees would be safe, would 
>> not rely on PID identity, and would be more efficient. Also way less 
>> coding. Also, it would be an old, established pattern - process 
>> groups have been around for a long time. Also, using process groups 
>> it is possible to break away from a group, so a program below you 
>> which wants to run as a demon can do so by removing itself from the 
>> process group and thus escaping your kill.
>>
>> On Windows we have Job objects, and I think there are enough 
>> similarities to POSIX process groups to abstract them into something 
>> platform independent.
> Earlier discussions of process termination and exit value reaping 
> considered
> using process groups but it became evident that the Java runtime 
> needed to
> be very careful to not interfere with processes that might be spawned and
> controlled by native libraries and that process groups would only 
> increase
> complexity and the interactions.
>
>>
>> The only problem I think is that the API would have somehow to be 
>> changed. Either by directly reflecting the use of process groups, or 
>> at least by removing allChildren() and replacing it with something 
>> like "killAllChildren()" or "signalAllChildren()".
>
> Thanks, Roger
>
>>
>> Kind Regards, Thomas
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> On Thu, Apr 9, 2015 at 10:00 PM, Roger Riggs <Roger.Riggs at oracle.com 
>> <mailto:Roger.Riggs at oracle.com>> wrote:
>>
>>     Please review the API and implementation of the Process API Updates
>>     described inJEP 102
>>     <https://bugs.openjdk.java.net/browse/JDK-8046092>. Please  review
>>     and comment by April 23rd.
>>
>>     The recommendation to make ProcessHandle an interface is included
>>     allowing the new functions to be extended by Process subclasses.
>>     The implementation covers all functions on Unix, Windows, Solaris,
>>     and Mac OS X.
>>
>>     The API doc: http://cr.openjdk.java.net/~rriggs/ph-apidraft/
>>     <http://cr.openjdk.java.net/%7Erriggs/ph-apidraft/>
>>
>>     The webrev: http://cr.openjdk.java.net/~rriggs/webrev-ph
>>     <http://cr.openjdk.java.net/%7Erriggs/webrev-ph>
>>
>>     Issue: JDK-8077350
>>     <https://bugs.openjdk.java.net/browse/JDK-8077350> Process API
>>     Updates Implementation
>>
>>     The code is in the jdk9 sandbox on branch JDK-8046092-branch.
>>
>>     Please review and comment, Roger
>>
>>
>>
>> On Thu, Apr 9, 2015 at 10:00 PM, Roger Riggs <Roger.Riggs at oracle.com 
>> <mailto:Roger.Riggs at oracle.com>> wrote:
>>
>>     Please review the API and implementation of the Process API Updates
>>     described inJEP 102
>>     <https://bugs.openjdk.java.net/browse/JDK-8046092>. Please  review
>>     and comment by April 23rd.
>>
>>     The recommendation to make ProcessHandle an interface is included
>>     allowing the new functions to be extended by Process subclasses.
>>     The implementation covers all functions on Unix, Windows, Solaris,
>>     and Mac OS X.
>>
>>     The API doc: http://cr.openjdk.java.net/~rriggs/ph-apidraft/
>>     <http://cr.openjdk.java.net/%7Erriggs/ph-apidraft/>
>>
>>     The webrev: http://cr.openjdk.java.net/~rriggs/webrev-ph
>>     <http://cr.openjdk.java.net/%7Erriggs/webrev-ph>
>>
>>     Issue: JDK-8077350
>>     <https://bugs.openjdk.java.net/browse/JDK-8077350> Process API
>>     Updates Implementation
>>
>>     The code is in the jdk9 sandbox on branch JDK-8046092-branch.
>>
>>     Please review and comment, Roger
>>
>>
>




More information about the core-libs-dev mailing list