@@ -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