[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