Bug 6585: BGP ChannelOutputLimiter waits forever 46/44946/2
authorMilos Fabian <milfabia@cisco.com>
Wed, 31 Aug 2016 15:40:49 +0000 (17:40 +0200)
committerMilos Fabian <milfabia@cisco.com>
Mon, 5 Sep 2016 12:07:15 +0000 (14:07 +0200)
After a while (when an output buffer reach upper bound),
BGP's ChannelOutputLimiter handler get stacked waiting for the channel to become writable again.
The writability change never happen, however socket flush is invoked,
so the session peer dies on holdtimer expiration.

Looks like calling #flush when writability changes to non-writable has no effect.
Invoking #flush in #ensureWritable makes the expected action.

Change-Id: I95681d87c30aff82ec360a2d13fc01fe35873507
Signed-off-by: Milos Fabian <milfabia@cisco.com>
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ChannelOutputLimiter.java

index 89cbe3ad3c3452a4dc2c8f7d88f7713894fcf474..ca818341b734b38a1c289e15403d61544fefb640 100644 (file)
@@ -37,6 +37,7 @@ public final class ChannelOutputLimiter extends ChannelInboundHandlerAdapter {
                 while (this.blocked) {
                     try {
                         LOG.debug("Waiting for session {} to become writable", this.session);
+                        flush();
                         this.wait();
                     } catch (final InterruptedException e) {
                         throw new IllegalStateException("Interrupted while waiting for channel to come back", e);
@@ -71,9 +72,7 @@ public final class ChannelOutputLimiter extends ChannelInboundHandlerAdapter {
             LOG.debug("Writes on session {} {}", this.session, w ? "unblocked" : "blocked");
 
             if (w) {
-                this.notifyAll();
-            } else {
-                flush();
+                notifyAll();
             }
         }
 
@@ -84,7 +83,7 @@ public final class ChannelOutputLimiter extends ChannelInboundHandlerAdapter {
     public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
         synchronized (this) {
             this.blocked = false;
-            this.notifyAll();
+            notifyAll();
         }
 
         super.channelInactive(ctx);