[rabbitmq-discuss] .Net RabbitMQ.Client Issue: Deadlock on ConnectionShutdown

Derek Greer dbgreer at gmail.com
Mon Aug 20 19:29:36 BST 2012


There appears to be a deadlock if you attempt to dispose, close, or abort a 
channel within the context of an IConnection.ConnectionShutdown event. 
 Here's an example client that should demonstrate the issue:

RabbitService.cs (needs to run as admin to shut down the Windows service)
-------------------------
using System;
using System.ServiceProcess;

namespace Consumer
{
public class RabbitService
{
public void Restart()
{
var serviceController = new ServiceController("RabbitMQ", "localhost");
TimeSpan timeout = TimeSpan.FromMilliseconds(20000);
Console.WriteLine("  Stopping RabbitMQ service ...");
serviceController.Stop();
serviceController.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
Console.WriteLine("  RabbitMQ service stopped.");
Console.WriteLine("  Starting RabbitMQ service ...");
serviceController.Start();
serviceController.WaitForStatus(ServiceControllerStatus.Running, timeout);
Console.WriteLine("  RabbitMQ service started.");
}

public void Start()
{
var serviceController = new ServiceController("RabbitMQ", "localhost");
TimeSpan timeout = TimeSpan.FromMilliseconds(20000);
Console.WriteLine("  Starting RabbitMQ service ...");
serviceController.Start();
serviceController.WaitForStatus(ServiceControllerStatus.Running, timeout);
Console.WriteLine("  RabbitMQ service started.");
}

public void Stop()
{
var serviceController = new ServiceController("RabbitMQ", "localhost");
TimeSpan timeout = TimeSpan.FromMilliseconds(20000);
Console.WriteLine("  Stopping RabbitMQ service ...");
serviceController.Stop();
serviceController.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
Console.WriteLine("  RabbitMQ service stopped.");
}
}
}

ConsumerProgram.cs
--------------------------------
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;

namespace Consumer
{
class Program
{
const string Id = "2BD27137-9AE3-4342-B4C3-9DEC20D203DF";
static Thread _thread;
static bool _threadCancelled;

static void Main(string[] args)
{
IConnection connection = new ConnectionFactory().CreateConnection();
connection.ConnectionShutdown += ConnectionShutdown;
SubscribeToQueue(connection);
Console.WriteLine("Press a key to restart the RabbitMQ service ...");
Console.ReadKey();
new RabbitService().Restart();
Console.WriteLine("Press a key to stop subscription ...");
Console.ReadKey();

if (connection.IsOpen)
{
connection.Close();
}
}

static void ConnectionShutdown(IConnection connection, ShutdownEventArgs 
reason)
{
Console.WriteLine("Connection was shut down");
Console.WriteLine("Sending the signal to cancel the thread ...");

// Setting _threadCancelled to true here causes a deadlock.
_threadCancelled = true;
_thread.Join();
}

static void SubscribeToQueue(IConnection connection)
{
_thread = new Thread(() =>
{
IModel channel = connection.CreateModel();

channel.ExchangeDeclare(Id, ExchangeType.Direct, false, true, null);
channel.QueueDeclare(Id, false, false, true, null);
channel.QueueBind(Id, Id, "");

var consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(Id, true, consumer);

while (true)
{
if (_threadCancelled)
{
Console.WriteLine("Received signal to cancel this thread.");
_threadCancelled = false;
break;
}

BasicDeliverEventArgs eventArgs = null;

try
{
object eArgs = null;
consumer.Queue.Dequeue(10, out eArgs);

if (eArgs != null)
{
eventArgs = (BasicDeliverEventArgs) eArgs;
string message = Encoding.UTF8.GetString(eventArgs.Body);
Console.WriteLine("Message: " + message);
}
}
catch (EndOfStreamException)
{
// Never happens
Console.WriteLine("Caught EndOfStreamException");
channel.Dispose();
channel = null;
break;
}
catch (Exception e)
{
Console.WriteLine("An exception occurred while dequeuing a message: " + 
e.Message, TraceEventType.Error);
}
}
if (channel != null && channel.IsOpen)
{
Console.WriteLine("Closing channel ...");
channel.Close(); // <- Never returns
Console.WriteLine("Channel closed.");
}

Console.WriteLine("End of thread execution.");
});

_thread.Start();
}
}
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/attachments/20120820/ab0fdca2/attachment.htm>


More information about the rabbitmq-discuss mailing list