RFR 9: 8077350 Process API Updates Implementation Review
Paul Sandoz
paul.sandoz at oracle.com
Mon May 18 21:16:00 UTC 2015
On May 18, 2015, at 10:49 PM, Roger Riggs <Roger.Riggs at Oracle.com> wrote:
> Hi Paul,
>
> Thanks for the comments.
>
> On 5/18/2015 7:58 AM, Paul Sandoz wrote:
>> Ho Roger,
>>
>> I mostly focused on the specification.
>>
>> Paul.
>>
>>
>> Process
>> --
>>
>> 35 * {@code Process} provides control of native processes started by
>> 36 * ProcessBuilder.start and Runtime.exec.
>>
>> Link to those methods?
> Links are not preferred in the first sentence used in the class summary.
> They are linked in the paragraph that follows
Ok, seems odd to me but oh well..
>>
>>
>> 92 /**
>> 93 * Default constructor for Process.
>> 94 */
>> 95 public Process() {}
>>
>> Is that redundant?
> It seemed good form to document the constructor exists.
> The implicit public zero-arg constructor can't have javadoc.
But there is nothing to say :-)
>>
>>
>> 251 /**
>> 252 * Kills the subprocess forcibly. The subprocess represented by this
>> 253 * {@code Process} object is forcibly terminated.
>> 254 * Forcible process destruction is defined as the immediate termination of a
>> 255 * process, whereas normal termination allows a process to shut down cleanly.
>> 256 * If the process is not alive, no action is taken.
>> 257 * <p>
>> 258 * The {@link java.util.concurrent.CompletableFuture} from {@link #onExit} is
>> 259 * {@link java.util.concurrent.CompletableFuture#complete completed}
>> 260 * when the process has terminated.
>> 261 *
> insert @implSpec
>> 262 * <p>The default implementation of this method invokes {@link #destroy}
>> 263 * and so may not forcibly terminate the process.
> insert @implNote
>> 264 * Concrete implementations of this class are strongly encouraged to override
>> 265 * this method with a compliant implementation.
> legacy spec - move up before other @ tags
>> 266 * Invoking this method on {@code Process} objects returned by
>> 267 * {@link ProcessBuilder#start} and {@link Runtime#exec} forcibly terminate
>> 268 * the process.
>> 269 *
>>
>> Use @ImplNote?
> Most of this is spec, not informational.
Sorry i meant @implSpec, including for the "Concrete impls..." bit.
>>
>>
>> 270 * <p>Note: The subprocess may not terminate immediately.
>> 271 * i.e. {@code isAlive()} may return true for a brief period
>> 272 * after {@code destroyForcibly()} is called. This method
>> 273 * may be chained to {@code waitFor()} if needed.
>> 274 *
>>
>> Use @apiNote?
> seems reasonable
> But the resulting javadoc breaks up the flow of information. the API note that a developer
> would want to know about is far from the rest of the method description.
Ok.
>>
>>
>> 361 * If the process is {@link #isAlive not alive} the {@link CompletableFuture}
>> 362 * is immediately {@link java.util.concurrent.CompletableFuture#complete completed}.
>>
>> s/is immediately/is returned/ ?
> The important action to be specified is that the CF is completed() immediately.
> Potentially it could say it is completed before the CF is returned from onExit().
>
Yeah, that is what i was trying to get across, it returns with an already completed CF.
>>
>>
>> 406 * @return a {@code CompletableFuture<Process>} for the Process;
>> 407 * a unique instance is returned for each call to {@code onExit}.
>> 408 *
>>
>> Any need to mention about unique instances?
> yes, since the hierarchy of the CF instances is visible to the app and it makes
> a difference whether a unique CF is returned for each call or whether
> the same CF is returned from each call.
Perhaps say "Returns a new CF..." and "@return a new {@code ..." ?
>>
>>
>> 429 /**
>> 430 * Returns a ProcessHandle for the Process.
>> 431 *
>>
>> Some methods talk about "the subprocess" where as others talk about "the Process" and others "the process".
> That variation of terminology predates this update.
I think it's best to try and be consistent throughout the class e.g. keep with the existing term or change to consistently use a new term.
>>
>>
>> 456 /**
>> 457 * Returns a snapshot of information about the process.
>> 458 *
>> 459 * <p> An {@link ProcessHandle.Info} instance has various accessor methods
>> 460 * that return information about the process, if the process is alive and
>> 461 * the information is available, otherwise {@code null} is returned.
>> 462 *
>> 463 * @implSpec
>> 464 * This implementation returns information about the process as:
>> 465 * {@link #toHandle toHandle().info()}.
>> 466 *
>> 467 * @return a snapshot of information about the process; non-null
>>
>> Dangling "non-null". Do you mean it's can never be null or ", otherwise null if the process is not alive or such information is not available"? I suspect the former now all Info methods return Optional.
> It is always non-null.
Ok, so the first paragraph needs tweaking.
>>
>>
>> 480 * <em>Note that processes are created and terminate asynchronously.
>> 481 * There is no guarantee that a process is {@link #isAlive alive}.
>> 482 * </em>
>>
>> s/terminate/terminated/
> Well sometimes the terminate themselves, 'terminated' sounds like it is an
> external actor performing the termination.
Ok.
>>
>>
>> ProcessHandle
>> --
>>
>> 79 * For example, EPERM on Linux.
>>
>> I presume you are referring to native process-related operations that return an error code of EPERM?
> Yes, but the example does not add much and I'll remove it.
Ok.
>>
>>
>> 86 /**
>> 87 * Returns the native process ID of the process. The native process ID is an
>> 88 * identification number that the operating system assigns to the process.
>> 89 *
>> 90 * @return the native process ID of the process
>> 91 * @throws UnsupportedOperationException if the implementation
>> 92 * does not support this operation
>> 93 */
>> 94 long getPid();
>>
>> In what cases could this throw a USO if the static "of "method did not?
> Its in an interface that might have arbitrary implementations. In a theoretical
> Process implementation for remote processes their might not be a viable pid
> or the access controls might be such that the PID is meaningless or restricted.
>
Ok, i think i get it: a call ProcessHandle.getPid obtained from ProcessHandle.of will never from a USO but other implementations of ProcessHandle might.
>>
>>
>> 326 * @return an {@code Optional<ProcessHandle>} for the process to be
>> 327 * forcibly destroyed;
>> 328 * the {@code Optional} has the value of the ProcessHandle
>> 329 * if the request to terminate was successful, otherwise it is empty
>> 330 * @throws IllegalStateException if the process is the current process
>> 331 */
>> 332 Optional<ProcessHandle> destroyForcibly();
>>
>> Under what cases would an empty optional be returned? e.g. if native permissions are not granted?
> yes, but Alan's and other remarks recommend changing the return type.
> boolean will cover case to reflect that it was not possible to request the process
> to be destroyed without creating a confusing state of an Optional.
Yes, that seems a better signal. What could the caller do if false is returned? not much i guess except log something.
Paul.
> Unless there is sufficient need for information about why the request was
> denied. That would suggest an exception be thrown with a os specific message.
More information about the core-libs-dev
mailing list