How to dispose a Poller with a blocked socket? - c#

I have single socket, which is blocked on sending the frame and I would like to dispose poller ( and everything related to it ). However, I cannot do it -- calling dispose on socket throws an exception, and calling dispose on poller completely blocks.
Please note, I am using SendFrame and I could use TrySendFrame, but the purpose of this example is to actually block the socket and find a way how to clean up everything.
Example:
private Program()
{
const string address = "tcp://localhost:5000";
var socket = new DealerSocket();
socket.Options.SendHighWatermark = 1;
socket.Options.Identity = Encoding.ASCII.GetBytes(Guid.NewGuid().ToString("N"));
socket.Connect(address);
var poller = new NetMQPoller();
poller.Add(socket);
socket.SendReady += OnSendReady;
poller.RunAsync();
Thread.Sleep(5000);
Console.WriteLine("Disposing");
poller.Dispose(); // get stuck on this one
Console.WriteLine("Disposed");
}
private void OnSendReady(object sender, NetMQSocketEventArgs e)
{
Console.WriteLine("0");
e.Socket.SendFrame("hello");
Console.WriteLine("1");
e.Socket.SendFrame("hello"); // this will block
Console.WriteLine("2");
}
Tested with NetMQ 3.3.3.4 (my primary version for now) and 4.0.0.1.

1) Always zeroize ZMQ_LINGER. Always. Right upon a socket instantiation, so as to prevent otherwise inadvertent blocking on graceful termination { .close() | .term() } operations ( be it a controlled or un-controlled activation of termination ops ( as you already have faced it ) ).
2) Avoid blocking designs. Principally. Each blocking state creates a state, in which all your code is out-of-control. Got it?

Related

How to wait for ManualResetEvent.WaitOne() to be reached before moving on?

I'm trying to use ManualResetEvent to make a semaphore-like situation and I have placed WaitOne, Set and Reset in their right places. The WaitOne instruction is called in a listener thread and is places right after a tcp reading:
var networkStream = _clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, Convert.ToInt32(_clientSocket.ReceiveBufferSize));
_mainthreadControl.WaitOne(Timeout.Infinite);
And Set and Reset instructions are called in another thread, so the socket won't get competed over:
try
{
//some code
_mainthreadControl.Reset();
//some code that uses the same socket as above
_mainthreadControl.Set();
}
catch (Exception ex)
{
//ignored
}
But I need the code to stop when it reaches Reset, and only continue after the WaitOne is reached (and executed), so the code below Reset only runs after the competing thread is waiting.
I don't know if I was clear enough, so I'm glad to add details as needed. Thanks in advance.
If it suites for you. Please try to use additional AutoResetEvent. Like this:
var _additionalControl = new AutoResetEvent(false);
// code gap
var networkStream = _clientSocket.GetStream();
networkStream.Read(bytesFrom, 0, Convert.ToInt32(_clientSocket.ReceiveBufferSize));
_additionalControl.Set();
_mainthreadControl.WaitOne(Timeout.Infinite);
// code gap
try
{
//some code
_mainthreadControl.Reset();
_additionalControl.WaitOne(Timeout.Infinite);
//some code that uses the same socket as above
_mainthreadControl.Set();
}
catch (Exception ex)
{
//ignored
}
In turn I recommend to use System.Threading.Monitor class, cause it's more faster than ManualResetEvent(false), because it's restricted by the single process. If course if you don't need to use lock in another program.

Cannot use breakpoint in the callback function of Socket.BeginConnect()

public bool Connect (string address, int remotePort)
{
if (_socket != null && _socket.Connected)
return true;
IPHostEntry hostEntry = Dns.GetHostEntry (address);
foreach (IPAddress ip in hostEntry.AddressList) {
try {
IPEndPoint ipe = new IPEndPoint (ip, remotePort);
_socket = new Socket (ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
break;
} catch (System.Exception e) {
PushPacket ((ushort)MsgIds.Id.CONNECTION_ATTEMPT_FAILED, e.Message);
return false;
}
}
return true;
}
void ConnectionCallback (System.IAsyncResult ar)
{
NetBitStream stream = new NetBitStream ();
stream._socket = (Socket)ar.AsyncState;
try {
_socket.EndConnect (ar);
_socket.SendTimeout = _sendTimeout;
_socket.ReceiveTimeout = _revTimeout;
PushPacket ((ushort)MsgIds.Id.CONNECTION_REQUEST_ACCEPTED, "");
_socket.BeginReceive (stream.BYTES, 0, NetBitStream.HEADER_LENGTH, SocketFlags.None, new System.AsyncCallback (ReceiveHeader), stream);
} catch (System.Exception e) {
if (e.GetType () == typeof(SocketException)) {
if (((SocketException)e).SocketErrorCode == SocketError.ConnectionRefused) {
PushPacket ((ushort)MsgIds.Id.CONNECTION_ATTEMPT_FAILED, e.Message);
} else
PushPacket ((ushort)MsgIds.Id.CONNECTION_LOST, e.Message);
}
Disconnect (0);
}
}
Here are two functions. When I call
client.Connect ("127.0.0.1", 10001);
It just steps over the break; after
_socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
and goes to return true;. I set a breakpoint at ConnectionCallback but it does not go into this function.
There is no server listening on the 10001 port.
So I think it at least should throw an exception (connect failed), then go into the catch.
Or have I made a mistake in the two functions?
Here is a Minimal, Complete, and Verifiable example
using System;
using System.Net.Sockets;
using System.Net;
namespace TestSocket
{
class MainClass
{
public static void Main (string[] args)
{
NetTCPClient tcp_client = new NetTCPClient ();
tcp_client.Connect ("127.0.0.1", 10001);
}
}
class NetTCPClient
{
Socket _socket = null;
public bool Connect (string address, int remote_port)
{
if (_socket != null && _socket.Connected)
return true;
IPHostEntry host_entry = Dns.GetHostEntry (address);
foreach (IPAddress ip in host_entry.AddressList) {
try {
IPEndPoint ipe = new IPEndPoint (ip, remote_port);
_socket = new Socket (ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult ia = _socket.BeginConnect (ipe, new System.AsyncCallback (ConnectionCallback), _socket);
break;
} catch (Exception e) {
Console.WriteLine ("Connet() catch an exception!");
return false;
}
}
return true;
}
void ConnectionCallback (System.IAsyncResult ar)
{
Console.WriteLine ("ConnectionCallback() ");
}
}
}
The debugger doesn't work that way. With very few exceptions, it will not switch threads without explicit instruction from you.
When you are stepping through the Connect() method you wrote, you are debugging a particular thread in your program. The ConnectionCallback() method, if and when it is called (note that it is not generally going to be called synchronously during your call to BeginConnect()), will be called in a different thread. If you want to debug it, you need to set a breakpoint at or in the ConnectionCallback() method itself.
With a breakpoint set in that method, you are assured that the debugger will pause the execution of your program there, regardless of which thread is executing that method.
EDIT:
Thank you for the full code example. Assuming that is in fact the code example you are testing with and having trouble with, then your problem is (as was already guessed) one of two things:
After stepping through the call to the Connect() method, you do not resume execution of your program. I.e. you did not click the "Continue" button or use the "Continue" menu item in the "Debug" menu. Or…
You do resume execution of your program, which then promptly exits before the connection attempt can be resolved.
In case #1 above, you never see the breakpoint because your program is not executing. The breakpoint can only be triggered if execution of the program does in fact arrive at the breakpoint. But the execution of your program can't arrive there if it's not happening at all.
In case #2 above, you never see the breakpoint because your program is not executing. In this case, it's because the program has exited altogether.
If you want to see the breakpoint at the ConnectionCallback() method get triggered, you need to let the program run, and for long enough for that to happen.
As a quick proof-of-concept, I set a breakpoint at that method, and added this statement to the end of the Main() method:
Thread.Sleep(TimeSpan.FromMinutes(5));
I then used the debugger to step through the Main() method. It of course paused to let the program run at the above statement I'd just added, but then very quickly interrupted the program again, right at the desired breakpoint. (I didn't have to wait anywhere close to 5 minutes…I just used that as a very large time value that I was sure would be enough).
For what it's worth, I also tried a test where I stepped through the original Main(), i.e. without the call to Thread.Sleep(), but waited about 5-10 seconds after stepping over the call to Connect() before proceeding. In that case, at least on my computer, I also did see the breakpoint triggered. That particular test is somewhat dependent on machine configuration, so it's less reliable than adding the call to Thread.Sleep(). But it did work in my case.
I think you may have misunderstood what BeginConnect does. That doesn't make the connection - it just starts making the connection, asynchronously. So yes, I'm not at all surprised that "step over" immediately steps to the next statement - that's working as intended.
However, I would have expected that a breakpoint in ConnectionCallback would be hit - that's what you should concentrate on as a problem. That's also where you should put the exception handling, as that's where any problems with making the connection would be found.
Alternatively, if you're using C# 5 or higher, you should look into using async/await, which would allow you to get rid of all the callbacks. Then you'll get a much more familiar experience when debugging - if you step over that line, it really will be connected (or there'll be a failure) by the time you hit the next line. Just be aware that other things may happen (even on the same thread) while it's "awaiting" the response.
Unfortunately, I can't see anything in Socket which implements the relevant pattern. You could use TaskFactory.FromAsync to adapt the "old" style to the "new" style, but it's likely to be fairly painful.
Another approach is to try to move to higher-level constructs like TcpClient instead of the lower-level Socket class.

C# thread started in another class

I have one main form class and another class. In the second class, I have a thread loop:
public void StartListening()
{
listening = true;
listener = new Thread(new ThreadStart(DoListening));
listener.Start();
}
// Listening for udp datagrams thread loop
/*=====================================================*/
private void DoListening()
{
while (listening)
{
IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, port);
byte[] content = udpClient.Receive(ref remoteIPEndPoint);
if (content.Length > 0)
{
string message = Encoding.ASCII.GetString(content);
delegMessage(message);
}
}
}
// Stop listening for udp datagrams
/*=====================================================*/
public void StopListening()
{
lock (locker)
{
listening = false;
}
}
In main form class, I start this listening in class constructor
udp.StartListening();
And than, in this main form class, I have key hook event, too. In this event, I wan to stop thread running in the second class.
private void hook_KeyPressed(int key)
{
if (key == (int)Keys.LMenu)
altPressed = true;
if (key == (int)Keys.F4 && altPressed == true)
udp.StopListening();
}
Unfortunetely, the thread is still running.
Do you have some ideas about this??
Thank you very much.
Your thread is blocking at the byte[] content = udpClient.Receive(ref remoteIPEndPoint); line. The Receive method blocks until something is received.
You should use the asynchronous version (BeginReceive) instead.
Also, another flaw in your code - you check for the stopping condition without any synchronization. Here:
private void DoListening()
{
while (listening){ //this condition could stuck forever in 'false'
}
Actually, without a memory barrier, there is no guarantee, that a thread, that is running DoListening will ever see the change to listening var from other thread. You should at least use locking here (which provides memory barrier)
As #igelineau pointed out - your code is blocking on the receive call. If you don;t want to go down the async route (which I'd recommend) just send something to the udp port in your stop listening method.

closing the port after joining thread or before joining the thread?

i want to get signal from port and I used these functions for receiving data,but I sometimes get this exception on line thread.join() :
System.IO.IOException was unhandled
Message="The I/O operation has been aborted because of either a thread exit or an application request.
when I insert a breakpoint and debug it, it goes correct until on line thread.join() and the UI then is stopped and nothings occurs.
also when I run my program in release mode it works correctly but the problem is with debug mode,what is goes wrong and how I can solve this problem?
thnx.
public SignalReader()
{
thread = new Thread(new ThreadStart(ThreadMain));
}
public void Start(string portName, int rate)
{
Stop();
try
{
port = new SerialPort(portName, rate);
port.Open();
}
catch
{
;
}
thread.Start();
}
public void Stop()
{
try
{
if (port != null)
{
if (port.IsOpen) port.Close();
if (thread.IsAlive) thread.Join();
port.Dispose();
port = null;
}
}
catch (Exception ex)
{
MessageBox.Show("4:" + ex.ToString());
}
}
when i swap the order of closing the port and joining the thread:
...
thread.Join();
port.Close();
...
the same story exists.
You are jerking the floor mat, closing the port while it is being used. Most typically in a SerialPort.Read() call. So, yes, that call is going to fail, there's no floor mat anymore. What's missing is a catch block that catches that exception and lets the thread end gracefully. And complete the Join() call.
It is not entirely unusual to do this, as long as you can make sure that the thread is actually blocking on such a Read call. That's not usually very hard to guarantee. But certainly fret about not getting that exception in the Release build, that's not normal. Use the debugger's Debug + Window + Threads to see what's going on in that worker thread.
So just add the required try/catch to fix your problem. Using the SerialPort.DataReceived event is an entirely different approach. Not cleaning up at all, just setting the thread's IsBackground property to true so it automatically dies when the program terminates is also a quite acceptable solution.
The error you are receiving is because of that Stop() you are using in:
public void Start(string portName, int rate)
{
Stop();
try
{
port = new SerialPort(portName, rate);
port.Open();
}
catch
{
;
}
thread.Start();
}
The app is doing something already and when you call this it closes a port is being in use somewhere.
Try removing it and you will get an exception in the Start method if the port is not closed. It will give you a better idea where this error comes from. Also could you paste the part of the code where you are using these methods?

What happens if you break out of a Lock() statement?

I'm writing a program which listens to an incoming TcpClient and handles data when it arrives. The Listen() method is run on a separate thread within the component, so it needs to be threadsafe. If I break out of a do while loop while I'm within a lock() statement, will the lock be released? If not, how do I accomplish this?
Thanks!
(Any other advice on the subject of Asynchronous TCP Sockets is welcome as well.)
private void Listen()
{
do
{
lock (_clientLock)
{
if (!_client.Connected) break;
lock (_stateLock)
{
if (!_listening) break;
if (_client.GetStream().DataAvailable) HandleData();
}
}
Thread.Sleep(0);
} while (true);
}
Yes. The lock statement translates into a try/finally clause. In C# 4, for example, a lock statement like so:
lock(obj)
{
// body
}
roughly translates (taken from Eric Lippert's blog here) to:
bool lockWasTaken = false;
var temp = obj;
try
{
Monitor.Enter(temp, ref lockWasTaken);
{
// body
}
}
finally
{
if (lockWasTaken)
Monitor.Exit(temp);
}
When the execution leaves the scope of the lock {}, the underlying lock will be released automatically. This will happen no matter how you exit scope (break/return/etc), since the call to Monitor.Exit is wrapped, internally, inside of the finally block of a try/finally.
Yes, the lock will be released. You can use ILDASM or Reflector to look at the actual generated code. The lock statement is shorthand for the following code (roughly).
Monitor.Enter(_client);
try
{
// do your stuff
}
finally {
Monitor.Exit(_client);
}
Notice the finally block is always executed.
Because you asked for other advice...I noticed that you are nesting locks. This, by itself, is not necessarily a bad thing. But, it is one my red flags I watch out for. There is the possibility of a deadlock if you ever acquire those two locks in a different order in another part of your code. I am not saying there is anything wrong with your code. It is just something else to watch out for because it is easy to get wrong.
Once you exit the lock{}, it will unlock what you have locked (it's just like a using statement in that regard). It doesn't matter where you exit (the beginning, the end, or the middle), it's that you left the scope of the lock at all. Think about what would happen if you raised an exception in the middle.
To answer the other half of your question:
Any other advice on the subject of Asynchronous TCP Sockets is welcome as well
Simply put I wouldn't manage this in the fashion demonstrated by your original post. Rather seek help from the System.Net.Sockets.TcpClient and the System.Net.Sockets.TcpListener classes. Use the async calls like BeginAcceptSocket(...) and BeginRead(...) and allow the ThreadPool to do it's job. It's really pretty easy to put together that way.
You should be able to achieve all the server behavior you desire without ever coding the dreaded words "new Thread" :)
Here is a basic example of the idea, minus the idea of graceful shutdown, exception handling ect:
public static void Main()
{
TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, 8080));
listener.Start();
listener.BeginAcceptTcpClient(OnConnect, listener);
Console.WriteLine("Press any key to quit...");
Console.ReadKey();
}
static void OnConnect(IAsyncResult ar)
{
TcpListener listener = (TcpListener)ar.AsyncState;
new TcpReader(listener.EndAcceptTcpClient(ar));
listener.BeginAcceptTcpClient(OnConnect, listener);
}
class TcpReader
{
string respose = "HTTP 1.1 200\r\nContent-Length:12\r\n\r\nHello World!";
TcpClient client;
NetworkStream socket;
byte[] buffer;
public TcpReader(TcpClient client)
{
this.client = client;
socket = client.GetStream();
buffer = new byte[1024];
socket.BeginRead(buffer, 0, 1024, OnRead, socket);
}
void OnRead(IAsyncResult ar)
{
int nBytes = socket.EndRead(ar);
if (nBytes > 0)
{
//you have data... do something with it, http example
socket.BeginWrite(
Encoding.ASCII.GetBytes(respose), 0, respose.Length, null, null);
socket.BeginRead(buffer, 0, 1024, OnRead, socket);
}
else
socket.Close();
}
}
For a much more complicated example of how to do this see the SslTunnel Library I wrote a while ago.

Categories

Resources