Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Socket.Connect blocks all threads?


  • Please log in to reply
35 replies to this topic

#1 Michiel

Michiel

    Member

  • Members
  • PipPip
  • 13 posts
  • LocationZwolle, The Netherlands

Posted 06 April 2011 - 02:45 PM

Hi,

while writing some networking code on my ND+, I found something strange with Socket. When I call Connect on a Socket, it blocks all threads in the program while it tries to connect to the endpoint. Example code below:
static void Connect()
{
    new Thread(BlinkStatusLed).Start();

    while (true)
    {
        try
        {
            _s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _s.Connect(new IPEndPoint(new IPAddress(new byte[] { 192, 168, 2, 4 }), 5678));
            _s.ReceiveTimeout = 5000;
            _connected = true;
            break;
        }
        catch (SocketException se)
        {
            // TODO
        }
    }

    _blinkStatusLed = false;
}

static void BlinkStatusLed()
{
    _blinkStatusLed = true;
    while (_blinkStatusLed)
    {
        _statusLed.Write(!_statusLed.Read()); // This is the on-board LED
        Thread.Sleep(500);
    }

    _statusLed.Write(true);
}
As soon as execution reaches the _s.Connect() line, the LED stops blinking, even though that code runs in another thread. Then, when the _s.Connect call fails after a while, the LED turns on/off (depending on the previous state), and then the thread blocks again when it reaches the _s.Connect call again.
Am I missing something, or is this simply not posssible?

#2 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 06 April 2011 - 03:31 PM

Try putting the socket code in it's own thread that way that thread blocks but the rest of the system remains responsive. Regards, Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#3 Michiel

Michiel

    Member

  • Members
  • PipPip
  • 13 posts
  • LocationZwolle, The Netherlands

Posted 06 April 2011 - 05:05 PM

Hi Nevyn,

Thanks for your reply.

I changed the code like this:
static void Connect()
{
    new Thread(BlinkStatusLed).Start();
    new Thread(MakeTcpConnection).Start();
}

static void MakeTcpConnection()
{
    while (true)
    {
        try
        {
            _s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _s.Connect(_master);
            _s.ReceiveTimeout = 5000;
            _connected = true;
            break;
        }
        catch (SocketException se)
        {
        }
    }

    _blinkStatusLed = false;
}

static void BlinkStatusLed()
{
    _blinkStatusLed = true;
    while (_blinkStatusLed)
    {
        _statusLed.Write(!_statusLed.Read());
        Thread.Sleep(500);
    }

    _statusLed.Write(true);
}
But it does the same. The LED only changes state (on<->off) when the _s.Connect method times out and throws an exception, then blocks again when the loop starts over and reaches the _s.Connect method again.

Any other ideas?

#4 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 06 April 2011 - 05:58 PM

Hi Michiel, That might be an implementation limitation of lwIP in the .NET MF core. .NET MF is a cooperatively-multitasked runtime. But the scheduler cannot switch tasks when managed code instructions are "stuck". It sounds like perhaps lwIP is waiting in a loop to connect instead of working asynchronously. Could you please post this bug over on the .NET MF project page (http://netmf.codeplex.com -> issue tracker)? We can follow up with Microsoft on it as well... Chris

#5 Michiel

Michiel

    Member

  • Members
  • PipPip
  • 13 posts
  • LocationZwolle, The Netherlands

Posted 06 April 2011 - 06:12 PM

Hi Chris, Thanks for your reply. I'm going to post it on the .NETMF CodePlex issue tracker :) I'll update this post with a link to the issue. Edit: link to the issue: http://netmf.codeplex.com/workitem/950

#6 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 06 April 2011 - 06:18 PM

.NET MF is a cooperatively-multitasked runtime. But the scheduler cannot switch tasks when managed code instructions are "stuck". It sounds like perhaps lwIP is waiting in a loop to connect instead of working asynchronously.

Could you please post this bug over on the .NET MF project page (http://netmf.codeplex.com -> issue tracker)? We can follow up with Microsoft on it as well...


In the meantime, if you need to get this going you can have a look at the Netduino Web Server code in this blog entry. This does multi-thread having code which collects data and also listens to the network for connections.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#7 Michiel

Michiel

    Member

  • Members
  • PipPip
  • 13 posts
  • LocationZwolle, The Netherlands

Posted 06 April 2011 - 06:30 PM

Hi Mark, Thanks, but there is a difference in application, in that the code in your link listens for connections (which actually works very well multi-threaded), whereas my code tries to connect to an endpoint itself :).

#8 Nevyn

Nevyn

    Advanced Member

  • Members
  • PipPipPip
  • 1072 posts
  • LocationNorth Yorkshire, UK

Posted 06 April 2011 - 07:36 PM

Thanks, but there is a difference in application, in that the code in your link listens for connections (which actually works very well multi-threaded), whereas my code tries to connect to an endpoint itself :).


Sorry - mis-read the post - I agree, the connection blocks the application even when in a seperate thread.

Regards,
Mark

To be or not to be = 0xFF

 

Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life

Follow @nevynuk on Twitter


#9 George Antoniadis

George Antoniadis

    Member

  • Members
  • PipPip
  • 25 posts

Posted 05 July 2011 - 12:23 PM

Is there an update about this on the 4.2 beta?

#10 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 05 July 2011 - 02:08 PM

Is there an update about this on the 4.2 beta?

I believe that this behavior has been improved in 4.2 beta 1+.

Chris

#11 George Antoniadis

George Antoniadis

    Member

  • Members
  • PipPip
  • 25 posts

Posted 06 July 2011 - 08:19 AM

I keep having weird problems with network connectivity and sockets. If the network cable is not plugged in or the endpoint is not reachable it keeps on trying pausing all threads. Also there still doesn't seem to be a timeout for when it will stop trying to connect. Is there a tried and proven way to verify ethernet connectivity and to actually manage to use sockets without pausing everything in 4.2?

#12 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 06 July 2011 - 05:25 PM

Hi George, Could you please post a bug report describing this behavior on netmf.codeplex.com? In theory, it's best if the TCP stack never blocks the rest of the runtime. For most features, this isn't an issue...but networking can be a tricky beast to iron out on embedded devices. I'm not sure that Microsoft is aware of this particular scenario. Chris

#13 dougY

dougY

    Member

  • Members
  • PipPip
  • 19 posts

Posted 06 July 2011 - 08:31 PM

anyone have experience with a netduino w/ ethernet shield generating this problem? i cant believe that you couldnt multi-thread a network call while still reading data. this is really making me wonder why i am porting all my code to this platform from java on a small linux box. i feel like i am wasting my time for the thousandth time on this project. has anyone played around with setting Thread priority?

#14 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 06 July 2011 - 08:59 PM

If the lwIP timeout is not working properly or .NET MF is not scheduling it properly, that's something that should be possible to fix for .NET MF 4.2 (which is in beta, and coming out pretty soon). But I'm not sure that Microsoft is aware of the issue, so we need to make sure that a few of us pitch in to a bug report at netmf.codeplex.com so they understand if it's not an isolated issue. Thread priority only affects managed threads--if there's a bug in the native lwIP layer, the managed runtime won't have a chance to switch priorities. Chris

#15 George Antoniadis

George Antoniadis

    Member

  • Members
  • PipPip
  • 25 posts

Posted 07 July 2011 - 01:18 PM

Before posting a bug report please verify this too.
The following code behaves differently on 4.1.x and 4.2b1. (Make sure the ip doesn't exist on your LAN or that the ethernet is not connected)

static void Main()
        {
            new Thread(BlinkStatusLed).Start();
            new Thread(Connect).Start();
        }

        static void Connect()
        {
            try
            {
                Debug.Print("TRY");
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Connect(new IPEndPoint(new IPAddress(new byte[] { 10, 10, 0, 43 }), 80));
                Debug.Print("DONE");
            }
            catch (SocketException e)
            {
                Debug.Print("THROW");
                throw;
            }
        }

        static void BlinkStatusLed()
        {
            OutputPort onboardLed = new OutputPort(Pins.ONBOARD_LED, false);
            while (true)
            {
                onboardLed.Write(!onboardLed.Read());
                Thread.Sleep(500);
            }
        }

On 4.1.x: Blocks the blink led thread and never reaches DONE or THROW.
On 4.2b1: The blink led thread keeps working as expected but never reaches DONE or THROW.

4.2b1 Is a very good step but the connection timeout cannot be set.
There are two timeouts available on the socket (SendTimeout and ReceiveTimeout) but not one for connect.
In the normal .NET frameworks in order to allow for Connection timeouts the AsyncCallback and socket.BeginConnect must be used, but in the micro framework the BeginConnect doesn't exist. So that's a no-go.

I tried hacking up a timeout emulation class for a project I am working on but I seem to be having a problem with the Thread.Abort() method.

How it works:
You create a new object ConnectionExtraThreaded, give it the endpoint ip, three callbacks (success, failure, timeout) and a timeout in milliseconds.

The object will start two threads. Connection and Timeout.
When the user specified timeout is reached the Timeout Thread will try to Abort() the Connection Thread.

This is where everything gets messy.
It keeps throwing an exception over and over again. I understand that this is normal .NET activity but can't find a way to properly kill the connection thread.

Any hints/ideas?

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace sample_sockets
{
    public delegate void ConnectionExtraThreadedSuccessCallback();
    public delegate void ConnectionExtraThreadedFailureCallback();
    public delegate void ConnectionExtraThreadedTimeoutCallback();

    public class ConnectionExtraThreaded
    {
        private IPEndPoint endPoint;
        private int millisecondsTimeout;
        private ConnectionExtraThreadedSuccessCallback successCallback;
        private ConnectionExtraThreadedFailureCallback failureCallback;
        private ConnectionExtraThreadedTimeoutCallback timeoutCallback;
        private Thread connectionThread;
        private Thread timeoutThread;

        public ConnectionExtraThreaded(IPEndPoint endPoint, ConnectionExtraThreadedSuccessCallback successCallback,
 ConnectionExtraThreadedFailureCallback failureCallback, ConnectionExtraThreadedTimeoutCallback timeoutCallback, 
 int millisecondsTimeout)
        {
            this.endPoint = endPoint;
            this.millisecondsTimeout = millisecondsTimeout;
            this.successCallback += successCallback;
            this.failureCallback += failureCallback;
            this.timeoutCallback += new ConnectionExtraThreadedTimeoutCallback(this.ConnectionThreadKill);
            this.timeoutCallback += timeoutCallback;

            this.connectionThread = new Thread(this.Connect);
            this.timeoutThread = new Thread(this.Timeout);

            this.connectionThread.Start();
            this.timeoutThread.Start();
        }

        private void Timeout()
        {
            Thread.Sleep(this.millisecondsTimeout);
            Debug.Print("ConnectionExtraThreaded: Connection timed out after " + this.millisecondsTimeout / 1000 + 
" seconds. Executing timeout callback.");
            this.timeoutCallback();
        }

        private void ConnectionThreadKill()
        {
            Debug.Print("ConnectionExtraThreaded: Killing connection thread.");
            this.connectionThread.Abort();
        }

        private void Connect()
        {
            try
            {
                Debug.Print("ConnectionExtraThreaded: Attempting connection.");
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                s.Connect(endPoint);
                Debug.Print("ConnectionExtraThreaded: Connection was successful. Executing success callback.");
                this.successCallback();
            }
            catch (System.Threading.ThreadAbortException e)
            {
                Debug.Print("ConnectionExtraThreaded: Connection aborted.");
            }
            catch (Exception e)
            {
                Debug.Print("ConnectionExtraThreaded: Connection died.");
            }

        }
    }

    public class Program
    {
        static void Main()
        {
            new Thread(BlinkStatusLed).Start();
            new Thread(Connect).Start();
        }

        static void Connect()
        {
            new ConnectionExtraThreaded(new IPEndPoint(new IPAddress(new byte[] { 10, 10, 0, 43 }), 80), 
  connectionSuccess, connectionFailure, connectionTimeout, 5000);
        }

        static void connectionSuccess()
        {
            Debug.Print("SUCCESS");
        }

        static void connectionTimeout()
        {
            Debug.Print("TIMEOUT");
        }

        static void connectionFailure()
        {
            Debug.Print("FAILED");
        }

        static void BlinkStatusLed()
        {
            OutputPort onboardLed = new OutputPort(Pins.ONBOARD_LED, false);
            while (true)
            {
                onboardLed.Write(!onboardLed.Read());
                Thread.Sleep(500);
            }
        }
    }
}


#16 Vincent Guillemette

Vincent Guillemette

    New Member

  • Members
  • Pip
  • 1 posts

Posted 13 July 2011 - 07:31 PM

I’m also having problems using sockets on Netduino Plus.

I tried with 4.1.x and 4.2 b1, and it's still freezing the Netduino Plus:

I discovered that the freeze occurs sometime during the socket instantiation. I assumed that the socket has to be disposed in order to clear the IP stack or something like it, so i tried to use the using() statement:

using (Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) trick.

Unfortunately it did not work. When it succesfully instanciated the socket, the connect statement does throw an exception only if my Ethernet cables is pluged. This is hard to test so I'm not sure.

I need this feature in my application, so thanks for the post to correct these problems.

The flashing led, is used to verify that the debugger is not involved in the forementioned problem.
Here my test code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace SocketFreeze
{
    public class Program
    {
        public static void Main()
        {
            OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);
            IPAddress address = IPAddress.Parse("192.168.1.142");
            IPEndPoint endPoint = new IPEndPoint(address, 80);
            using (Socket mySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                try
                {
                    mySocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
                    mySocket.Connect(endPoint);
                }
                catch (SocketException e)
                {
                    Debug.Print("Socket Exception" + e.ToString());
                }
                mySocket.Close();
            }

            while (true)
            {
                Thread.Sleep(500);
                led.Write(true);
                Thread.Sleep(500);
                led.Write(false);
            }
        }

    }
}


#17 George Antoniadis

George Antoniadis

    Member

  • Members
  • PipPip
  • 25 posts

Posted 14 July 2011 - 06:56 AM

Vincent as I said in the previous post the problem occurs (at least in 4.2b1) on the socket connection when the endpoint ip is not reachable or the cable is unplugged. The socket connection doesn't have a timeout property and the thread will never get disposed. On your code the problem is on the .connect and not on the new socket part. Consider adding your socket stuff in a separate thread for the time being until we find a proper way to do this. Also please remember that the threads will keep alive if they don't manage to connect and may pile up.

#18 George Antoniadis

George Antoniadis

    Member

  • Members
  • PipPip
  • 25 posts

Posted 14 July 2011 - 07:16 AM

I posted a basic bug report on the sockets connect timeouts and blocking. http://netmf.codeple...m/workitem/1089 Please vote for it if you are interested so maybe someone will take the time and help! :D

#19 James

James

    Advanced Member

  • Members
  • PipPipPip
  • 56 posts

Posted 17 July 2011 - 06:52 PM

It looks like both codeplex issues have been closed. Has anyone had a chance to verify that the behavior is improved in 4.2 b2?

#20 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 17 July 2011 - 07:32 PM

It looks like both codeplex issues have been closed. Has anyone had a chance to verify that the behavior is improved in 4.2 b2?

Hi James,

Is 4.2 beta 2 published yet on CodePlex? I looked for it to rebuild the firmware, but it looks like the core is still in flux (i.e. no milestone yet).

Chris




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.