Skip to content

Commit ba98383

Browse files
committed
Avoid race during worker startup
1 parent d47f9fc commit ba98383

File tree

1 file changed

+17
-19
lines changed

1 file changed

+17
-19
lines changed

junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ConcurrentHierarchicalTestExecutorService.java

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -128,21 +128,29 @@ private void forkAll(Collection<WorkQueue.Entry> entries) {
128128
}
129129

130130
private void maybeStartWorker() {
131-
if (threadPool.isShutdown() || !workerLeaseManager.isLeaseAvailable() || workQueue.isEmpty()) {
131+
if (threadPool.isShutdown() || workQueue.isEmpty()) {
132+
return;
133+
}
134+
var workerLease = workerLeaseManager.tryAcquire();
135+
if (workerLease == null) {
132136
return;
133137
}
134138
try {
135139
threadPool.execute(() -> {
136140
LOGGER.trace(() -> "starting worker");
137-
try {
138-
WorkerThread.getOrThrow().processQueueEntries();
141+
try (workerLease) {
142+
WorkerThread.getOrThrow().processQueueEntries(workerLease);
139143
}
140144
finally {
141145
LOGGER.trace(() -> "stopping worker");
142146
}
147+
// An attempt to start a worker might have failed due to no worker lease being
148+
// available while this worker was stopping due to lack of work
149+
maybeStartWorker();
143150
});
144151
}
145152
catch (RejectedExecutionException e) {
153+
workerLease.release();
146154
if (threadPool.isShutdown()) {
147155
return;
148156
}
@@ -200,21 +208,15 @@ ConcurrentHierarchicalTestExecutorService executor() {
200208
return ConcurrentHierarchicalTestExecutorService.this;
201209
}
202210

203-
void processQueueEntries() {
211+
void processQueueEntries(WorkerLease workerLease) {
212+
this.workerLease = workerLease;
204213
while (!threadPool.isShutdown()) {
205-
var workerLease = workerLeaseManager.tryAcquire();
206-
if (workerLease == null) {
214+
var entry = workQueue.poll();
215+
if (entry == null) {
207216
break;
208217
}
209-
try (workerLease) {
210-
var entry = workQueue.poll();
211-
if (entry == null) {
212-
break;
213-
}
214-
LOGGER.trace(() -> "processing: " + entry.task);
215-
this.workerLease = workerLease;
216-
execute(entry);
217-
}
218+
LOGGER.trace(() -> "processing: " + entry.task);
219+
execute(entry);
218220
}
219221
}
220222

@@ -581,10 +583,6 @@ private ReacquisitionToken release() {
581583
return new ReacquisitionToken();
582584
}
583585

584-
boolean isLeaseAvailable() {
585-
return semaphore.availablePermits() > 0;
586-
}
587-
588586
private class ReacquisitionToken {
589587

590588
private boolean used = false;

0 commit comments

Comments
 (0)