[PATCH] Fix race-condition of asynchronously closed channels

Victor Boivie victor at boivie.com
Wed Mar 27 06:22:04 GMT 2013


When a channel is closed from the server side due to errors we
have to send CloseOk before we can make it available for allocation
again. If not, we risk handing it out to a client which will open it
when it's not yet fully closed, which results in a
"COMMAND_INVALID - second 'channel.open' seen".

diff --git a/src/com/rabbitmq/client/impl/ChannelN.java
b/src/com/rabbitmq/client/impl/ChannelN.java
index 18e4f6a..9fe11c3 100644
--- a/src/com/rabbitmq/client/impl/ChannelN.java
+++ b/src/com/rabbitmq/client/impl/ChannelN.java
@@ -471,7 +471,6 @@ public class ChannelN extends AMQChannel implements
com.rabbitmq.client.Channel
     }

     private void asyncShutdown(Command command) throws IOException {
-        releaseChannel();
         ShutdownSignalException signal = new ShutdownSignalException(false,
                                                                      false,

command,
@@ -484,6 +483,7 @@ public class ChannelN extends AMQChannel implements
com.rabbitmq.client.Channel
                 notifyOutstandingRpc(signal);
             }
         }
+        releaseChannel();
         notifyListeners();
     }

--e89a8f923cfe1fa0d404d8e21fb8
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">I have been having some problems with the java-rabbitmq-cl=
ient when stress testing it. I frequently get &quot;COMMAND_INVALID - secon=
d &#39;channel.open&#39; seen&quot;, which eventually closes the connection=
 (not just the channel).<div>
<br></div><div style>It seems that there is a race condition when channels =
are closed asynchronously (due to errors), and created in other threads. Th=
e channel that is closed (by the server) doesn&#39;t seem to be fully close=
d before another thread can try to open a channel with the same number.</di=
v>
<div style><br></div><div style>The code to reproduce it is at=A0<a href=3D=
"https://github.com/boivie/rmq-stress-test">https://github.com/boivie/rmq-s=
tress-test</a></div><div style><br></div><div style>A possible fix is below=
.</div>
<div style><br></div><div style>Thanks,</div><div style>Victor</div><div st=
yle><br></div><div style><div>From 213cf8ef15a759985bc9dd74496548236b5160f2=
 Mon Sep 17 00:00:00 2001</div><div>From: Victor Boivie &lt;<a href=3D"mail=
to:victor at boivie.com">victor at boivie.com</a>&gt;</div>
<div>Date: Wed, 27 Mar 2013 07:22:04 +0100</div><div>Subject: [PATCH] Fix r=
ace-condition of asynchronously closed channels</div><div><br></div><div>Wh=
en a channel is closed from the server side due to errors we</div><div>
have to send CloseOk before we can make it available for allocation</div><d=
iv>again. If not, we risk handing it out to a client which will open it</di=
v><div>when it&#39;s not yet fully closed, which results in a</div><div>
&quot;COMMAND_INVALID - second &#39;channel.open&#39; seen&quot;.</div><div=
><br></div><div>diff --git a/src/com/rabbitmq/client/impl/ChannelN.java b/s=
rc/com/rabbitmq/client/impl/ChannelN.java</div><div>index 18e4f6a..9fe11c3 =
100644</div>
<div>--- a/src/com/rabbitmq/client/impl/ChannelN.java</div><div>+++ b/src/c=
om/rabbitmq/client/impl/ChannelN.java</div><div>@@ -471,7 +471,6 @@ public =
class ChannelN extends AMQChannel implements com.rabbitmq.client.Channel</d=
iv>
<div>=A0 =A0 =A0}</div><div>=A0</div><div>=A0 =A0 =A0private void asyncShut=
down(Command command) throws IOException {</div><div>- =A0 =A0 =A0 =A0relea=
seChannel();</div><div>=A0 =A0 =A0 =A0 =A0ShutdownSignalException signal =
=3D new ShutdownSignalException(false,</div>
<div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fal=
se,</div><div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0=
 =A0 command,</div><div>@@ -484,6 +483,7 @@ public class ChannelN extends A=
MQChannel implements com.rabbitmq.client.Channel</div>
<div>=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0notifyOutstandingRpc(signal);</div>=
<div>=A0 =A0 =A0 =A0 =A0 =A0 =A0}</div><div>=A0 =A0 =A0 =A0 =A0}</div><div>=
+ =A0 =A0 =A0 =A0releaseChannel();</div><div>=A0 =A0 =A0 =A0 =A0notifyListe=
ners();</div><div>=A0 =A0 =A0}</div><div>=A0</div></div></div>

--e89a8f923cfe1fa0d404d8e21fb8--


More information about the rabbitmq-discuss mailing list