RFR: 8303133: Update ProcessTools.startProcess(...) to exit early if process exit before linePredicate is printed. [v2]

David Holmes dholmes at openjdk.org
Mon Feb 27 05:22:09 UTC 2023


On Sat, 25 Feb 2023 00:19:33 GMT, Leonid Mesnik <lmesnik at openjdk.org> wrote:

>> The solution proposed by Stefan K
>> 
>> The startProcess() might wait forever for the expected line if the process exits (failed to start). It makes sense to just fail earlier in such cases.
>> 
>> The fix also move
>> 'output = new OutputAnalyzer(this.process);'
>> in method xrun() to be able to try to print them in waitFor is failed/interrupted.
>
> Leonid Mesnik has updated the pull request incrementally with one additional commit since the last revision:
> 
>   updated to always check if process is alive.

I have a number of issues with the changes. I think you have basically addressed the problem of waiting forever if no predicate line was forthcoming, but I think you have introduced a race with normal termination of the process.

test/lib/jdk/test/lib/process/ProcessTools.java line 220:

> 218:             if (timeout > -1) {
> 219:                 // Every second check if process is still alive
> 220:                 boolean succeeded = Utils.waitForCondition(() -> {

This use of `waitForCondition` with a sleep time of zero confused me quite a bit. Now I realize that you are putting `waitForCondition` into a potential busy-poll loop, but then you introduce the one-second timed `await` as part of the condition, thus effectively checking the condition once a second. This seems somewhat convoluted compared to just using a sleep time of 1000ms and changing the `await` to a call to `getCount() > 0`.

test/lib/jdk/test/lib/process/ProcessTools.java line 223:

> 221:                     //Fail if process finished before printed expected string
> 222:                     if (!p.isAlive()) {
> 223:                         latch.countDown();

This `countdown` serves no purpose. The latch is used to coordinate the current thread and the stream pumper thread: the current thread calls `await` and the streamPumper calls `countDown`. Here the current thread is not going to call `await` and it doesn't need to `countDown` to release itself.

test/lib/jdk/test/lib/process/ProcessTools.java line 224:

> 222:                     if (!p.isAlive()) {
> 223:                         latch.countDown();
> 224:                         throw new RuntimeException("Started process " + name + " is not alive.");

This seems problematic. The process has terminated but you don't know why - it may have completed normally and produced all the output such that the `await` below would return immediately with `true`, but you are now going to throw an exception. ???

test/lib/jdk/test/lib/thread/ProcessThread.java line 153:

> 151:         @Override
> 152:         public void xrun() throws Throwable {
> 153:             String name = Thread.currentThread().getName();

The original code passes the name of the `ProcessRunnable` to `startProcess`, not the name of the current thread. It is not obvious/apparent that they are the same. But if they are then it is cheaper to use `name` than do a dynamic query on the current thread.

-------------

Changes requested by dholmes (Reviewer).

PR: https://git.openjdk.org/jdk/pull/12751


More information about the core-libs-dev mailing list