diff --git a/bramble-core/src/main/java/org/briarproject/bramble/connection/DuplexSyncConnection.java b/bramble-core/src/main/java/org/briarproject/bramble/connection/DuplexSyncConnection.java index 0ed62ab0b..55be56812 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/connection/DuplexSyncConnection.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/connection/DuplexSyncConnection.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.concurrent.Executor; import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; import static org.briarproject.bramble.api.nullsafety.NullSafety.requireNonNull; @@ -33,8 +34,30 @@ abstract class DuplexSyncConnection extends SyncConnection { final TransportConnectionWriter writer; final TransportProperties remote; + private final Object interruptLock = new Object(); + + @GuardedBy("interruptLock") @Nullable - volatile SyncSession outgoingSession = null; + private SyncSession outgoingSession = null; + @GuardedBy("interruptLock") + private boolean interruptWaiting = false; + + void interruptOutgoingSession() { + synchronized (interruptLock) { + if (outgoingSession == null) interruptWaiting = true; + else outgoingSession.interrupt(); + } + } + + void setOutgoingSession(SyncSession outgoingSession) { + synchronized (interruptLock) { + this.outgoingSession = outgoingSession; + if (interruptWaiting) { + outgoingSession.interrupt(); + interruptWaiting = false; + } + } + } DuplexSyncConnection(KeyManager keyManager, ConnectionRegistry connectionRegistry, @@ -57,9 +80,7 @@ abstract class DuplexSyncConnection extends SyncConnection { void onReadError(boolean recognised) { disposeOnError(reader, recognised); disposeOnError(writer); - // Interrupt the outgoing session so it finishes - SyncSession out = outgoingSession; - if (out != null) out.interrupt(); + interruptOutgoingSession(); } void onWriteError() { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/connection/IncomingDuplexSyncConnection.java b/bramble-core/src/main/java/org/briarproject/bramble/connection/IncomingDuplexSyncConnection.java index 382b17a50..ba780cbc5 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/connection/IncomingDuplexSyncConnection.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/connection/IncomingDuplexSyncConnection.java @@ -68,9 +68,7 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection // Create and run the incoming session createIncomingSession(ctx, reader).run(); reader.dispose(false, true); - // Interrupt the outgoing session so it finishes cleanly - SyncSession out = outgoingSession; - if (out != null) out.interrupt(); + interruptOutgoingSession(); } catch (DbException | IOException e) { logException(LOG, WARNING, e); onReadError(true); @@ -91,7 +89,7 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection try { // Create and run the outgoing session SyncSession out = createDuplexOutgoingSession(ctx, writer); - outgoingSession = out; + setOutgoingSession(out); out.run(); writer.dispose(false); } catch (IOException e) { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/connection/OutgoingDuplexSyncConnection.java b/bramble-core/src/main/java/org/briarproject/bramble/connection/OutgoingDuplexSyncConnection.java index 0c8f464fb..ed6d21d05 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/connection/OutgoingDuplexSyncConnection.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/connection/OutgoingDuplexSyncConnection.java @@ -60,7 +60,7 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection try { // Create and run the outgoing session SyncSession out = createDuplexOutgoingSession(ctx, writer); - outgoingSession = out; + setOutgoingSession(out); out.run(); writer.dispose(false); } catch (IOException e) { @@ -104,9 +104,7 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection // Create and run the incoming session createIncomingSession(ctx, reader).run(); reader.dispose(false, true); - // Interrupt the outgoing session so it finishes cleanly - SyncSession out = outgoingSession; - if (out != null) out.interrupt(); + interruptOutgoingSession(); } catch (DbException | IOException e) { logException(LOG, WARNING, e); onReadError();