Problems on Compact Framework when communication is lost - c#

I have a problem on a hand held device that should be listening for messages from my server application. When the device loses connection to the network my server is on, this background worker (implemented from OpenNetCF) stops responding. I've placed messages in the ProgressChanged and RunWorkerCompleted events to see when they are raised, and in the following code after the RecieveFrom in the while loop, and after the loop termination, as well as in all of the exceptions. I don't see the messages from the exceptions, or after the while loop at all, and the messages stop after the connection is lost. All of the messages are shown by setting the text in a visible label, with the background colour of the label changing so that I can see if the loop is running. The loop seems to stop running, even after the connection is re-gained, and attempting to re-run the backgroundworker generates an "Already in use" exception. So, why would the worker stop responding while continuing to run?
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker wWorker = (BackgroundWorker)sender;
byte[] wBytes = new Byte[4096];
string wsReceive;
EndPoint wRemoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
try
{
while (true)
{
if (wWorker.CancellationPending)
{
break;
}
mSocket.ReceiveFrom(wBytes, ref wRemoteEP);
if (wBytes.Length < 1)
{
continue;
}
wsReceive = Encoding.ASCII.GetString(wBytes, 0, wBytes.Length);
wWorker.ReportProgress(0, wsReceive);
}
mSocket.Close();
}
catch (ThreadAbortException)
{
}
catch (ThreadStateException)
{
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Communication Error");
}
}

Right from the docs on Socket.ReceiveFrom:
If no data is available for reading, the ReceiveFrom method will block until data is available
So when communication is lost, you're unable to receive and your ReceiveFrom call blocks indefinitely. It's going to stop reporting anything while it waits for data, but the thread is still alive and therefore the BackgroundWorker can't be re-run.

Just my 2 cents:
Whenever I implement a socket communication, I treat 0 bytes received as an indication that the remote server has closed gracefully. I think that you should also treat this to start a reconnection attempt, instead of just "continuing" the loop.

Related

Correct way to timeout asynchronous namedpipes in C# .net environoment

I have a process that might have multiple instances running at anytime. Each instance should only run for several seconds at most. A process might have to pass data to an earlier started instance, or receive data from a latter started instance using named pipes. Each instance is aware of each other, but doesn't know for sure if it will attempt to pass or receive data. The process has a pipe server and client that each runs on its own thread. Since the process doesn't know before hand if the other process needs to send or receive data, I need the ability to attempt a connection but to time out and close the pipe if it hasn't connected in a few seconds. I'm using the asynch NamedPipeServer.BeginWaitForConnection() method. But I'm not sure if i'm using it correctly.
The process starts with Main() creating a thread with the
receiveServer() method.
receiveServer() starts a NamedPipeServer in a using block and starts the BeginWaitForConnection() method.
the AsychWaitHandle(3000) is used in the if condition so that if it successfully connects the readMessage(namedPipeServer) and a timeout timer is started. If the AsychWaitHandle(3000) expires then control goes to the else block where NamedPipeServer.Close() method is called.
The holdtimer runs as a safeguard while readMessage() method is running in case the pipeserver connects, and waits for data that never comes. When holdtimer expires it calls and event handler that calls the pipe server's close() method.
Being new to some of this, my main questions and concerns with my code are the fact that namedPipeServer.EndWaitForConnection(asynchResult) is only called int the event that the connection succeeds. According to the documentation EndWait must be called exacly once for each BeginWait. Testing the application, if no connection is made in 3 seconds the logic just falls through to the else block and then the pipe is closed, sometimes twice with out throwing any exception.
I'm also concerned about the way that I use the namedpipeserver.close() method in the timeout event when there is a hangup. That can call an exception readMessage() because the while loop tests while (!namedPipeServer.IsMessageComplete) which might be tested on a closed pipe.
I apologize for the lack of brevity, but I thought it would be a clearer question if I included all the relevant parts of the code.
Thanks in advance for the help.
public static void readMessage(NamedPipeServerStream namedPipeServer)
{
//While block continues while the Read() method has not complete,
// but once the Read() begins even if no data is available it blocks
//and the while block continues. Which is the reason for the
//timeout.
{
//Read from pipe to a global string variable
namedPipeServer.Read(messageBuffer, 0, messageBuffer.Length);
}
while (!namedPipeServer.IsMessageComplete);
}
public static void receiveServer()
{
try
{
using (NamedPipeServerStream namedPipeServer = new NamedPipeServerStream("test-pipe", PipeDirection.InOut,
1, PipeTransmissionMode.Message, PipeOptions.Asynchronous))
{
var asynchResult = namedPipeServer.BeginWaitForConnection(null, null);
//Adds a delegate to a timer that explicitly closes the pipe server on timeout
holdtimer.Elapsed += new ElapsedEventHandler((sender, e) => clockExpired(sender, e, namedPipeServer));
holdtimer.AutoReset = true;
//If connection succeeds within 3 seconds
//then control goes to the "if block" where
//the read method is called. And the hold timer
//is started. If the connection doesn't succeed in 3
//seconds then the named pipe server Close() method is called.
if (asynchResult.AsyncWaitHandle.WaitOne(3000))
{
//
namedPipeServer.EndWaitForConnection(asynchResult);
//start timer before calling method
holdtimer.Start();
//Pass namedAPipeServer to readMessage
readMessage(namedPipeServer);
//stop timer after method completes
holdtimer.Stop();
}
else
{
Console.WriteLine("didn't get anything ----------");
}
//Explicately close the PipeServer.
namedPipeServer.Close();
}
}
catch (Exception ex)
{
//This is just for testing.
MessageBox.Show("Exception in receiveMessage :" + ex.Message);
}
}
static void Main(string[] args)
{
//assign clockExpired() delgate to holdtimer
Thread receiverThread = new Thread(receiveServer);
receiverThread.Start();
}

HttpWebRequest timing out, but no packets leaving client

I have a c# application with the following requirements.
Periodically(700ms) send data to a cgi using a GET.
The server will respond with only the GET string sent as confirmation.
Values sent are constantly changing and are not stored, ordered, or retried.
Only one connection made to the server at a time.
Timer events that find a previous connection still in progress should simply exit quietly and let the next event carry on.
The client machine is Windows Server 2012. The HTTP server is a black box appliance(believed to be running linux). Environment is low-latency production with extremely tight security(network/policies/etc).
The problem:
Periodically, the client will begin throwing exceptions
"The operation timed out"
and the drip feed stops. Simultaneously, Wireshark shows
no connections being made from the client to the server.
However, VisualStudio shows that
every 700ms the client is attempting to connect and is timing out.
When it's not throwing the above exception, it seems to work fine. At no time does the HTTP server appear to be rejecting connections. Sometimes the client will recover, most of the time it will continue to throw exceptions until restarted. AppDomain thread pool is stable. Memory consumption is fine.
To confuse matters, I have identical hardware/software/network without the security in a lab where everything runs flawlessly for days at a time. My code is being fingered as "malfunctory".
I have recently discovered that the HttpWebRequest.Timeout property bounds the entire life of the transaction, not just the response wait. I am increasing this and it's currently under test.
Anyone see anything glaring(or otherwise) that would cause this problem in the below code?
// timer call back at 700ms interval
void m_postTimer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
if (Interlocked.Read(ref this.m_isLocked) == 0)
{
if (Monitor.TryEnter(this.m_lock, 10))
{
Interlocked.Exchange(ref this.m_isLocked, 1);
try
{
// value1 & value2 set elsewhere
string url = String.Format("http://1.1.1.1/set.cgi?value1={0}&value2={1}", value1, value2);
this.m_post = (HttpWebRequest)WebRequest.Create(url);
this.m_post.Timeout = 500;
this.m_post.Credentials = new NetworkCredential(this.user, this.pass);
WebResponse response = this.m_post.GetResponse();
response.Close();
Monitor.Exit(this.m_lock);
Interlocked.Exchange(ref this.m_isLocked, 0);
}
catch (WebException ex)
{
// handle web exceptions
// if we've locked earlier and hit an exception,
// the unlock has been skipped. unlock
if (Interlocked.Read(ref this.m_isLocked) > 0)
{
Monitor.Exit(this.m_lock);
Interlocked.Exchange(ref this.m_isLocked, 0);
}
}
}
}
else
{
// indicate that a pre-existing connection is still in progress
}
}
catch (Exception ex)
{
// handle generic exception
// if we've locked earlier and hit an exception,
// the unlock has been skipped. unlock
if (Interlocked.Read(ref this.m_isLocked) > 0)
{
Monitor.Exit(this.m_lock);
Interlocked.Exchange(ref this.m_isLocked, 0);
}
}
}

Try Catch exception in a locked block of code

I have an issue when there is an exception in a block of code that uses a lock. I am reading and writing to a serial port and there are several different threads that need access to the same serial port. This is managed by a lock. I have no issues except if the serial port stops working. This can happen since the software controls an RF transmitter and occasionally the rf can cause usb to serial ports to stop functioning. If you then attempt to write to the port you will get a write timeout. I tried handling this from a try - catch exception handler. However, the program locks hard at that point and has to have the task killed. I am not sure if this is coming from the exception or the message box I am trying to display since it could result from a background thread. Here is the code:
lock (_object)
{
try
{
if (portOpened)
{
port.Write(data);
}
else
{
MessageBox.Show("The radio is not connected. Please select a ComPort in the settings dialog");
}
}
catch (Exception x) //this will capture a write exception.
{
MessageBox.Show("The program is unable to write to the serial port. Select OK to close the program";
Application.Exit();
}
finally
{
}
}
Thanks for any help
If you want to force to exit the app, Application.Exit is not a good candidate, as it simply pushes the Close request on message queues of all threads, but does not force anything. If you want to stop app at any cost, use Environment.Exit(exitCode), or may be even better Environment.FailFast, with specified exception so it will be logged into the system's log: convenient for future investigations.

SerialPort UnauthorizedAccessException

Occasionally some of my integration tests are failing with the above message. I'm using the code below to ready the port.
for(int i = 0; i < 5; i++)
{
try
{
port.Open();
if (port.IsOpen)
break;
}
catch (Exception e)
{
try
{
port.Close();
}
catch (Exception)
{}
Thread.Sleep(300);
}
}
My assumption is that because it can't be the current thread blocking the port (because it will try to close it), it must be another thread or process that has died without cleaning up properly (one of the other tests - nothing else accesses this port). Is there a way to reset the state of the SerialPort so that the new thread / process can access it again?
Thanks,
Richard
This is a flaw in the SerialPort class, it uses an internal helper thread to wait for events on the port. The source of the DataReceived, PinChanged and ErrorReceived events. The flaw is in the Close() method implementation, it doesn't wait for this helper thread to terminate. That takes time, the exact amount of time is not predictable and could be many seconds when the machine is particularly busy. The physical port doesn't get closed until this happens, opening the port before the thread exits bombs with a 'port already in use' exception. The one you get. Sleeping for 300 msec is thus not good enough.
This is not normally an issue, serial ports are not sharable devices. Closing a serial port and not exiting your program is dangerous, another process could steal the port. Also giving you this exception when you try to open it again. The normal practice is to open the port when your app starts and not close it until it terminates.
I routinely verify that the port is closed just before I instantiate a serial port. This helps if you stop debugging code without closing the serial port. Also you should wait 250 msec after opening or closing the port before you continue with your code.
try
{
if (m_SerialPort != null)
{
if (m_SerialPort.IsOpen)
{
m_SerialPort.Close();
}
}
m_SerialPort = new SerialPort(portName, dataRate, parity, databits, stopBits.One);
m_SerialPort.Open();
if (!m_SerialPort.IsOpen)
{
MessageBox.Show(string.Concat(portName, " failed to open"));
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I can't see where you close the port.
The issue for me is not here (even if you should refactor a bit the code) but probably you are calling port.Open(); when the port is still open
From MSDN
Only one open connection can exist per SerialPort object.
(I can't tell you why because I don't have enough information) Bear also in mind the the close method takes some time to actually close the port in fact you should block the main thread until the port has been close (perhaps using Thread.Join)
From MSDN
The best practice for any application is to wait for some amount of time after calling the Close method before attempting to call the Open method, as the port may not be closed instantly.
for more info
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx
GC.SuppressFinalize should be called passing the SerialPort instance BaseStream property as the parameter and not just the SerialPort instance.
public class SerialConnection : SerialPort
{
public new void Dispose()
{
if (_isDisposed)
return;
_isDisposed = true;
BaseStream.Dispose();
GC.SuppressFinalize(BaseStream);
base.Dispose();
GC.SuppressFinalize(this);
}
The new void Dispose() of course is not the recommended way to implement IDisposable. It's merely a fix for the odd behaviour of the SerialPort class.

WSACancelBlockingCall exception

Ok, I have a strange exception thrown from my code that's been bothering me for ages.
System.Net.Sockets.SocketException: A blocking operation was interrupted by a call to WSACancelBlockingCall
at System.Net.Sockets.Socket.Accept()
at System.Net.Sockets.TcpListener.AcceptTcpClient()
MSDN isn't terribly helpful on this : http://msdn.microsoft.com/en-us/library/ms741547(VS.85).aspx and I don't even know how to begin troubleshooting this one. It's only thrown 4 or 5 times a day, and never in our test environment. Only in production sites, and on ALL production sites.
I've found plenty of posts asking about this exception, but no actual definitive answers on what is causing it, and how to handle or prevent it.
The code runs in a separate background thread, the method starts :
public virtual void Startup()
{
TcpListener serverSocket= new TcpListener(new IPEndPoint(bindAddress, port));
serverSocket.Start();
then I run a loop putting all new connections as jobs in a separate thread pool. It gets more complicated because of the app architecture, but basically:
while (( socket = serverSocket.AcceptTcpClient()) !=null) //Funny exception here
{
connectionHandler = new ConnectionHandler(socket, mappingStrategy);
pool.AddJob(connectionHandler);
}
}
From there, the pool has it's own threads that take care of each job in it's own thread, separately.
My understanding is that AcceptTcpClient() is a blocking call, and that somehow winsock is telling the thread to stop blocking and continue execution.. but why? And what am I supposed to do? Just catch the exception and ignore it?
Well, I do think some other thread is closing the socket, but it's certainly not from my code.
What I would like to know is: is this socket closed by the connecting client (on the other side of the socket) or is it closed by my server. Because as it is at this moment, whenever this exception occurs, it shutsdown my listening port, effectively closing my service. If this is done from a remote location, then it's a major problem.
Alternatively, could this be simply the IIS server shutting down my application, and thus cancelling all my background threads and blocking methods?
Is it possible that the serverSocket is being closed from another thread? That will cause this exception.
This is my example solution to avoid WSAcancelblablabla:
Define your thread as global then you can use invoke method like this:
private void closinginvoker(string dummy)
{
if (InvokeRequired)
{
this.Invoke(new Action<string>(closinginvoker), new object[] { dummy });
return;
}
t_listen.Abort();
client_flag = true;
c_idle.Close();
listener1.Stop();
}
After you invoke it, close the thread first then the forever loop flag so it block further waiting (if you have it), then close tcpclient then stop the listener.
This could happen on a serverSocket.Stop(). Which I called whenever Dispose was called.
Here is how my exception handling for the listen thread looked like:
try
{
//...
}
catch (SocketException socketEx)
{
if (_disposed)
ar.SetAsCompleted(null, false); //exception because listener stopped (disposed), ignore exception
else
ar.SetAsCompleted(socketEx, false);
}
Now what happened was, every so often the exception would occur before _disposed was set to true. So the solution for me was to make everything thread safe.
Same here!
But i figured out, that the ReceiveBuffer on 'server-side' was flooded from the clients!
(In my case a bunch of RFID-Scanners, who kept spamming the TagCode, instead of stop sending until next TagCode arrives)
It helped to raise the ReceiveBuffers and reconfigure the scanners...
More recently I saw this exception when using HttpWebRequest to PUT a large file and the Timeout period was passed.
Using the following code as long as your upload time > 3 seconds it will cause this error as far as I could see.
string path = "Reasonably large file.dat";
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
System.Net.HttpWebRequest req = (HttpWebRequest)System.Net.HttpWebRequest.Create("Some URL");
req.Method = "PUT";
req.Timeout = 3000; //3 seconds, small timeout to demonstrate
long length = new System.IO.FileInfo(path).Length;
using (FileStream input = File.OpenRead(path))
{
using (Stream output = req.GetRequestStream())
{
long remaining = length;
int bytesRead = 0;
while ((bytesRead = input.Read(buffer, 0, (int)Math.Min(remaining, (decimal)bufferSize))) > 0)
{
output.Write(buffer, 0, bytesRead);
remaining -= bytesRead;
}
output.Close();
}
input.Close();
}

Categories

Resources