Strange behaviour

I got following code:


public void SendData2Server(string sValue)
        {
            while (true)
            {
                Thread tSendServerBugWrapper = new Thread(() => SendData2ServerBugWrapper(sValue));
                tSendServerBugWrapper.Start();
                tSendServerBugWrapper.Join(2000);
                if (tSendServerBugWrapper.IsAlive)
                {
                    tSendServerBugWrapper.Abort();
                    //tSendServerBugWrapper.Join();
                }
            }
        }

private void SendData2ServerBugWrapper(string sValue)
        {
            while (IPAddress.GetDefaultLocalAddress().ToString() == "0.0.0.0")
                Thread.Sleep(500);

            using (var clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ApplicationSettings.ServerIP), ApplicationSettings.ServerPort);
                clientSocket.Connect(serverEndPoint);
                byte[] msg = Encoding.UTF8.GetBytes(sValue + "<EOF>");
                clientSocket.Send(msg);
                clientSocket.Close();
            }
        }

The MF client connect to server over tcp sockets. If server is not available, the thread is aborted, because there is no exception or timeout on Socket.connect (or i’m missing something?).
This code works fine, when I start it within Visual Studio (in debugging mode). However, when I started it as standalone, just with FEZ spider usb connected to my computer, the code not works as from Visual Studio. When I inspect messages with MF deploy, when thread aborted is called, the connection with Spider is lost.
I’m confused, because code works within Visual Studio, but not in “production” environment.

Any tip would be appreciated.

What does this mean?

It means that spider freezes.

Your code will go into a loop, repeating the thread creation if the connection is not made within 2 seconds.

When the Spider freezes what is happening? You can not ping it with MFDeploy? You can not deploy a program?

Might be a good idea to post a complete small program which someone could use to recreate the problem.

Thanks for suggestions, but I just made a little progress.
Yes, in my old example, I couldn’t ping it with MFDeploy.
The logic is correct - application that uses this snippet just reads some values from analog input, and send them to server via sockets. All sending logic is in this little snippet, and yes, you’re correct - if timeout occures (in this example 2 seconds) the thread is killed.
I made corrections and eliminate “using” statement. I declare Socket object above the try catch block, so that I could manually close socket. I don’t know what, but there is something wrong, if I abort thread when it hangs on Socket.Connect.

Now it does not hang immediately, but it’s allows me to kill much more threads, when server is down (around 50 requests, I just testing it now). It then hangs also, but this situation is much better. Here is new code snippet:


private void SendData2ServerBugWrapper(string sValue)
        {
            while (IPAddress.GetDefaultLocalAddress().ToString() == "0.0.0.0")
                Thread.Sleep(500);

            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("xxx.xxx.xxx.xxx"), 11000);
                clientSocket.Connect(serverEndPoint);

                byte[] msg = Encoding.UTF8.GetBytes(sValue + "<EOF>");
                clientSocket.Send(msg);
                clientSocket.Close();
                m_IsSendDataSuccedded = true;
            }
            catch (ThreadAbortException ex)
            {
                clientSocket.Close();
                clientSocket = null;
            }
            catch (Exception e)
            {
                Debug.Print("Error   ::  " + e.Message);
            }
          
        }

        public bool SendData2Server(string sValue)
        {
            try
            {
                Thread tSendServerBugWrapper = new Thread(() => SendData2ServerBugWrapper(sValue));
                tSendServerBugWrapper.Start();
                tSendServerBugWrapper.Join(2000);
                if (tSendServerBugWrapper.IsAlive)
                {
                    tSendServerBugWrapper.Abort();
                    //tSendServerBugWrapper.Join();
                }
            }
            catch { return false; }
            return m_IsSendDataSuccedded; ;
        }

Here is snippet to try out, you don’t need server, because in this bug, it’s assumed, that server is down. Just add in your main timer, or thread to call SendData2Server periodically. I gues that framework doesn’t dispose Socket objects as should have to?

Thanks

Would be interesting to see what is happening with memory. Might be useful to monitor the free memory with a Debug.GC(false) statement and when it gets to a low point start flashing a LED.

Memory looks ok. I include Debug.GC(false) and inspect MFDeploy debug window, just before it hangs.

in the thread abort exception handler try doing a dispose after the close.

Mike, what can I say. I love you very much :slight_smile:
Manual dispose is the right way.
In case that anyone runs into this trouble, here is the code:


private void SendData2ServerBugWrapper(string sValue)
        {
            while (IPAddress.GetDefaultLocalAddress().ToString() == "0.0.0.0")
                Thread.Sleep(500);

            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(ApplicationSettings.ServerIP), ApplicationSettings.ServerPort);
                clientSocket.Connect(serverEndPoint);

                byte[] msg = Encoding.UTF8.GetBytes(sValue + "<EOF>");
                clientSocket.Send(msg);
                clientSocket.Close();
                m_IsSendDataSuccedded = true;
            }
            catch (ThreadAbortException ex)
            {
                if (clientSocket != null)
                {
                    clientSocket.Close();
                    ((IDisposable)clientSocket).Dispose();
                }
            }
            catch (Exception e)
            {
                Debug.Print("Error   ::  " + e.Message);
            }
        }
        
        public bool SendData2Server(string sValue)
        {
            try
            {
                Thread tSendServerBugWrapper = new Thread(() => SendData2ServerBugWrapper(sValue));
                tSendServerBugWrapper.Start();
                tSendServerBugWrapper.Join(2000);
                if (tSendServerBugWrapper.IsAlive)
                {
                    tSendServerBugWrapper.Abort();
                    tSendServerBugWrapper.Join();
                }
            }
            catch (Exception ex) { Debug.Print(ex.Message); return false; }
            return m_IsSendDataSuccedded; ;
        }

Great!

@ Mike - That is really interesting, is this an issue you came across before with .NETMF? I took a look at the code and the Socket.Close() is implemented as follows


public void Close()
{
  ((IDisposable)this).Dispose();
} 

So I wonder why explicitly calling Dispose() makes a difference, is this pointing to a bigger issue? Would be interesting to see if removing the call to Close but keeping the Dispose still works or just calling Close twice???

I just guessed this might help. :slight_smile:

Is this the only line in close method?

@ Mike - It scares me that it worked :slight_smile: . Good guess, I would never have gone there…

@ tvinko - Yes, I copied that code straight from the 4.2 framework source code. Here is the codeplex location

https://netmf.svn.codeplex.com/svn/client_v4_2/Framework/Core/System/System/Net/Sockets/Socket.cs

That is interesting. Perhaps you should also post the question to the Microsoft Gadgeteer forum and see what they have to say about it. Makes no sense to me. Perhaps it changes the priority in GC by having a local Dispose and causes it to get collected sooner?

I’m doing some test, and problem started again, also with this new code. Apparently it was just coincidence that application start working with new code. I’m investigating further. I read somewhere that some strange things can happen, if FEZ doesn’t have own power. I power it up from usb. There is also maybe something wrong with my usb cable… It seems that this is not software problem.

Anyway, thank you all for help and tips. For now, I do reboot, if there is no buffer space available.


 private void SendData2ServerBugWrapper(string sValue)
        {
            while (IPAddress.GetDefaultLocalAddress().ToString() == "0.0.0.0")
                Thread.Sleep(500);
            
            try
            {
                SendDataByServerIP(ApplicationSettings.ServerIP, ApplicationSettings.ServerPort, sValue);
            }
            catch (SocketException eex)
            {
                if (eex.ErrorCode == 10055)
                {
                    try
                    {
                        SendDataByServerIP(ApplicationSettings.AlternateServerIP, ApplicationSettings.AlternateServerPort, sValue);
                    }
                    catch (SocketException ex)
                    {
                        if (eex.ErrorCode == 10055)
                            DoReboot = true;
                    }
                }
            }

private void SendDataByServerIP(string sServerIP, int iServerPort, string sValue)
        {
            using (Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                try
                {
                    IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse(sServerIP), iServerPort);
                    clientSocket.Connect(serverEndPoint);

                    byte[] msg = Encoding.UTF8.GetBytes(sValue + "<EOF>");
                    clientSocket.Send(msg);
                    clientSocket.Close();
                    m_IsSendDataSuccedded = true;
                }
                catch (Exception ex)
                {
                    Debug.Print("Exception");
                }
                finally
                {

                }
            }
        }
        }