mirror of
https://github.com/apache/maven-mvnd.git
synced 2025-09-11 21:50:38 +00:00
Fix daemon connection race condition (#1078)
The Server was using a SynchrnousQueue to coordinate the main thread and the background thread that receives the request from the client. A SynchronousQueue only allows insertions when a corresponding call to `get` is in progress. However, since the receiver thread is started before the call to `get`, there was a short time window, where the call to `queue.offer` could fail and simply return `false`. This return code was ignored. A possible solution would have been to call `put` instead of `offer`, but I decided to replace the queue with a Future, since we only wait for a single element. Co-authored-by: Stefan Oehme <st.oehme@gmail.com>
This commit is contained in:
@@ -37,11 +37,11 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.locks.Condition;
|
import java.util.concurrent.locks.Condition;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
@@ -271,13 +271,13 @@ public class Server implements AutoCloseable, Runnable {
|
|||||||
|
|
||||||
try (DaemonConnection connection = new DaemonConnection(socket)) {
|
try (DaemonConnection connection = new DaemonConnection(socket)) {
|
||||||
LOGGER.info("Waiting for request");
|
LOGGER.info("Waiting for request");
|
||||||
SynchronousQueue<Message> request = new SynchronousQueue<>();
|
CompletableFuture<Message> request = new CompletableFuture<>();
|
||||||
new DaemonThread(() -> {
|
new DaemonThread(() -> {
|
||||||
Message message = connection.receive();
|
Message message = connection.receive();
|
||||||
request.offer(message);
|
request.complete(message);
|
||||||
})
|
})
|
||||||
.start();
|
.start();
|
||||||
Message message = request.poll(1, TimeUnit.MINUTES);
|
Message message = request.get(1, TimeUnit.MINUTES);
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
LOGGER.info("Could not receive request after one minute, dropping connection");
|
LOGGER.info("Could not receive request after one minute, dropping connection");
|
||||||
updateState(DaemonState.Idle);
|
updateState(DaemonState.Idle);
|
||||||
|
Reference in New Issue
Block a user