This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
commit 1c86ff471bf25a1b69fd47ce7d05aaace89f1c86 Author: Guillaume Nodet <[email protected]> AuthorDate: Sun Jun 7 06:47:49 2026 +0000 Fix IpcServer Lock.unlock() — complete futures outside monitor F-20: Collect futures to complete during the synchronized block but complete them after releasing the Lock monitor, preventing I/O operations (socket writes in thenRun callbacks) from being serialized under the lock. --- .../org/eclipse/aether/named/ipc/IpcServer.java | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcServer.java b/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcServer.java index 9f58fb7e2..b7ae0a03f 100644 --- a/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcServer.java +++ b/maven-resolver-named-locks-ipc/src/main/java/org/eclipse/aether/named/ipc/IpcServer.java @@ -442,24 +442,29 @@ public class IpcServer { return future; } - public synchronized void unlock(Context context) { - if (holders.remove(context)) { - while (waiters != null - && !waiters.isEmpty() - && (holders.isEmpty() || holders.get(0).shared && waiters.get(0).context.shared)) { - Waiter waiter = waiters.remove(0); - holders.add(waiter.context); - waiter.future.complete(null); - } - } else if (waiters != null) { - for (Iterator<Waiter> it = waiters.iterator(); it.hasNext(); ) { - Waiter waiter = it.next(); - if (waiter.context == context) { - it.remove(); - waiter.future.cancel(false); + public void unlock(Context context) { + List<CompletableFuture<Void>> toComplete; + synchronized (this) { + toComplete = new ArrayList<>(); + if (holders.remove(context)) { + while (waiters != null + && !waiters.isEmpty() + && (holders.isEmpty() || holders.get(0).shared && waiters.get(0).context.shared)) { + Waiter waiter = waiters.remove(0); + holders.add(waiter.context); + toComplete.add(waiter.future); + } + } else if (waiters != null) { + for (Iterator<Waiter> it = waiters.iterator(); it.hasNext(); ) { + Waiter waiter = it.next(); + if (waiter.context == context) { + it.remove(); + waiter.future.cancel(false); + } } } } + toComplete.forEach(f -> f.complete(null)); } public synchronized boolean isEmpty() {
