8313290: Misleading exception message from STS.Subtask::get when task forked after shutdown

Reviewed-by: psandoz
This commit is contained in:
Alan Bateman 2023-08-19 18:42:43 +00:00
parent febc34dd28
commit ed0f75f266
2 changed files with 8 additions and 23 deletions

View File

@ -576,8 +576,6 @@ public class StructuredTaskScope<T> implements AutoCloseable {
} }
SubtaskImpl<U> subtask = new SubtaskImpl<>(this, task, round); SubtaskImpl<U> subtask = new SubtaskImpl<>(this, task, round);
boolean started = false;
if (s < SHUTDOWN) { if (s < SHUTDOWN) {
// create thread to run task // create thread to run task
Thread thread = factory.newThread(subtask); Thread thread = factory.newThread(subtask);
@ -588,15 +586,14 @@ public class StructuredTaskScope<T> implements AutoCloseable {
// attempt to start the thread // attempt to start the thread
try { try {
flock.start(thread); flock.start(thread);
started = true;
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// shutdown by another thread, or underlying flock is shutdown due // shutdown by another thread, or underlying flock is shutdown due
// to unstructured use // to unstructured use
} }
} }
// force owner to join if thread started // force owner to join if this is the first fork in the round
if (started && Thread.currentThread() == flock.owner() && round > forkRound) { if (Thread.currentThread() == flock.owner() && round > forkRound) {
forkRound = round; forkRound = round;
} }
@ -939,7 +936,8 @@ public class StructuredTaskScope<T> implements AutoCloseable {
T r = (T) result; T r = (T) result;
return r; return r;
} }
throw new IllegalStateException("Subtask not completed or did not complete successfully"); throw new IllegalStateException(
"Result is unavailable or subtask did not complete successfully");
} }
@Override @Override
@ -949,7 +947,8 @@ public class StructuredTaskScope<T> implements AutoCloseable {
if (result instanceof AltResult alt && alt.state() == State.FAILED) { if (result instanceof AltResult alt && alt.state() == State.FAILED) {
return alt.exception(); return alt.exception();
} }
throw new IllegalStateException("Subtask not completed or did not complete with exception"); throw new IllegalStateException(
"Exception is unavailable or subtask did not complete with exception");
} }
@Override @Override

View File

@ -279,6 +279,7 @@ class StructuredTaskScopeTest {
executed.set(true); executed.set(true);
return null; return null;
}); });
scope.join();
assertEquals(Subtask.State.UNAVAILABLE, subtask.state()); assertEquals(Subtask.State.UNAVAILABLE, subtask.state());
assertThrows(IllegalStateException.class, subtask::get); assertThrows(IllegalStateException.class, subtask::get);
assertThrows(IllegalStateException.class, subtask::exception); assertThrows(IllegalStateException.class, subtask::exception);
@ -673,22 +674,6 @@ class StructuredTaskScopeTest {
} }
} }
/**
* Test that shutdown prevents new threads from starting.
*/
@Test
void testShutdownWithFork() throws Exception {
ThreadFactory factory = task -> null;
try (var scope = new StructuredTaskScope<Object>(null, factory)) {
scope.shutdown();
// should not invoke the ThreadFactory to create thread
Subtask<Void> subtask = scope.fork(() -> null);
assertEquals(Subtask.State.UNAVAILABLE, subtask.state());
assertThrows(IllegalStateException.class, subtask::get);
assertThrows(IllegalStateException.class, subtask::exception);
}
}
/** /**
* Test that shutdown interrupts unfinished subtasks. * Test that shutdown interrupts unfinished subtasks.
*/ */
@ -1377,6 +1362,7 @@ class StructuredTaskScopeTest {
// fork after shutdown // fork after shutdown
Subtask<Void> subtask = scope.fork(task); Subtask<Void> subtask = scope.fork(task);
scope.join();
assertEquals(task, subtask.task()); assertEquals(task, subtask.task());
assertEquals(Subtask.State.UNAVAILABLE, subtask.state()); assertEquals(Subtask.State.UNAVAILABLE, subtask.state());
assertThrows(IllegalStateException.class, subtask::get); assertThrows(IllegalStateException.class, subtask::get);