Fixed deadlock in AsyncSshHandlerWriter 84/81784/2
authorJaroslav Tóth <jtoth@frinx.io>
Tue, 2 Apr 2019 03:41:32 +0000 (05:41 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 29 Apr 2019 08:25:53 +0000 (10:25 +0200)
Deadlock happened when listener for window is resized
and write is invoked at the same time.

Change-Id: I8c662d6cd5edbc3e36b31a754d826f79bec76434
Signed-off-by: Martin Sunal <msunal@frinx.io>
Signed-off-by: Jaroslav Tóth <jtoth@frinx.io>
(cherry picked from commit 0f45153d60a0fc71a08d011e21fdf5e83c174290)

netconf/netconf-netty-util/src/main/java/org/opendaylight/netconf/nettyutil/handler/ssh/client/AsyncSshHandlerWriter.java

index cabd33b40a510f127555ef5098e6dda23ab9986b..6540a6451f4fdea51d986ca175419a6d9f0ce540 100644 (file)
@@ -17,6 +17,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.Deque;
 import java.util.LinkedList;
 import java.util.Queue;
+import javax.annotation.concurrent.GuardedBy;
 import org.apache.sshd.common.io.IoOutputStream;
 import org.apache.sshd.common.io.WritePendingException;
 import org.apache.sshd.common.util.buffer.Buffer;
@@ -50,6 +51,9 @@ public final class AsyncSshHandlerWriter implements AutoCloseable {
         this.asyncIn = asyncIn;
     }
 
+    @GuardedBy("asyncInLock")
+    private boolean isWriteExecuted = false;
+
     public void write(final ChannelHandlerContext ctx,
             final Object msg, final ChannelPromise promise) {
         if (asyncIn == null) {
@@ -67,7 +71,7 @@ public final class AsyncSshHandlerWriter implements AutoCloseable {
                 promise.setFailure(new IllegalStateException("Channel closed"));
             } else {
                 final ByteBuf byteBufMsg = (ByteBuf) msg;
-                if (!pending.isEmpty()) {
+                if (isWriteExecuted) {
                     queueRequest(ctx, byteBufMsg, promise);
                     return;
                 }
@@ -86,6 +90,9 @@ public final class AsyncSshHandlerWriter implements AutoCloseable {
             if (LOG.isTraceEnabled()) {
                 LOG.trace("Writing request on channel: {}, message: {}", ctx.channel(), byteBufToString(byteBufMsg));
             }
+
+            isWriteExecuted = true;
+
             asyncIn.writePacket(toBuffer(byteBufMsg)).addListener(future -> {
                 // synchronized block due to deadlock that happens on ssh window resize
                 // writes and pending writes would lock the underlyinch channel session
@@ -134,6 +141,7 @@ public final class AsyncSshHandlerWriter implements AutoCloseable {
     private void writePendingIfAny() {
         synchronized (asyncInLock) {
             if (pending.peek() == null) {
+                isWriteExecuted = false;
                 return;
             }