Forum

You must be logged in to post Login


Lost Your Password?

Search Forums:


 






Wildcard Usage:
*    matches any number of characters
%    matches exactly one character

Bug in TCP Server: Consuming 100% CPU

No Tags
UserPost

10:11 am
April 19, 2011


Markus M.

Guest

Post edited 12:22 pm – April 19, 2011 by Paul


Hello,

we want to use your OSC Library in our program DMXControl.

 

We found a bug in the TCP Server. It used 100% of CPU.

 

Here is how we fixed it:

 

TcpServer.cs

 

Replace :

try

            {

                mIsShuttingDown = false;

                mReceiveData = true;

                Socket workerSocket;

                listener = new TcpListener(mIPAddress, mPort);                

                listener.Start(MaxPendingConnections);

                while (mAcceptingConnections)

                {

                    if (listener.Pending())

                    {

                        workerSocket = listener.AcceptSocket();

                        Thread workerThread = new Thread(RunWorker);

                        workerThread.Start(workerSocket);

                    }

                }

            }

 

With:

try

            {

                mIsShuttingDown = false;

                mReceiveData = true;

                listener = new TcpListener(mIPAddress, mPort);                

                listener.Start(MaxPendingConnections);

                while (mAcceptingConnections)

                {

                    mClientConnected.Reset();

                    listener.BeginAcceptSocket(new AsyncCallback(OnClientSockenAcceptBeginCallback), listener);

                    mClientConnected.WaitOne();

                }

            }

 

Add in region Private Methods:

 

private void OnClientSockenAcceptBeginCallback(IAsyncResult ar)

        {

            TcpListener listener = (TcpListener)ar.AsyncState;

            Socket workerSocket = listener.EndAcceptSocket(ar);

#if WINDOWS

            Thread workerThread = new Thread(RunWorker);

            workerThread.Start(workerSocket);

#else

            ThreadStartDelegateWrapper threadStartWrapper = new ThreadStartDelegateWrapper(new ThreadStartWrapperHandler(RunWorker), workerSocket);

            Thread workerThread = new Thread(new ThreadStart(threadStartWrapper.Start));

            workerThread.Start();

#endif

            mClientConnected.Set();

        }

1:42 pm
April 21, 2011


Paul

Admin

posts 49

Post edited 1:43 pm – April 21, 2011 by Paul


Hello Markus,

Thank you for your post. I've known about this issue for awhile now, but have never addressed it. Your solution works beautifully, and I've integrated it with the 1.7 release of the library. One note to pass along (though you may have already done this): be sure to include a mClientConnected.Set() call in the TcpServer.Stop() method, otherwise the listener thread will block.

I've addressed a number of additional issues with the 1.7 release, including a fix to inline, asynchronous data handling within TcpServer. Thus, I've toggled the default data handling from synchronous to asycnhronous, addressing a thread blocking issue when the server stops with actively connected clients.

Also, I've checked out your DMXControl website. Looks like a cool piece of software.

Thanks again.

Paul

5:02 am
April 22, 2011


Soon5

Guest

Hy Paul,

Thanks for the flowers. The Fix was from me. Your right, when you say that there has to be an additional Set in the Stop() Method.

But while i was looking at the code i found something else. (V1.7)

In the Stop() Method you do

{


mAcceptingConnections = false;

mReceiveData = false;

mIsShuttingDown = true;

mListenerReady.Set();


}

 

But you don't set mAcceptingConnections to true again in the Start() Method

{


TcpListener listener = null;

try

{

mIsShuttingDown = false;

mReceiveData = true;


 

And when I look at the code, the only point where mAcceptingConnections is set besides Stop() is in the Constructor where you're initializing the variables. In my opinion you've got to set mAcceptingConnections to in Start() where you're setting mReceiveData to true. The result is, when you Stop the Server one time, it'll never accept Connections after it is restarted.

Greetings from another code addicted guy.

Arne Lüdtke

 

10:09 am
April 22, 2011


Paul

Admin

posts 49

Hi Arne,

You're absolutely correct. I have apparently never tested restarting the server from the same process (I really need to add a bona-fide suite of unit tests). I've applied the change to the existing 1.7 release without issuing a completely new 1.8 release. If you haven't applied the fix yourself, you might want to re-download the 1.7 release.

Thanks for the heads up, and thanks again for the original fix. I'm glad you've found the library useful.

Paul

No Tags

About the Bespoke Software forum



No Comment

Comments are closed.