[muscle] Re: Growing Win32 HANDLE count with repetive connection attempts

  • From: "Jeremy Friesner" <jaf@xxxxxxxxxxxx>
  • To: muscle@xxxxxxxxxxxxx
  • Date: Wed, 06 Oct 2004 08:59:09 PDT (-0700)

Hi Raymond,

I don't see any glaring mistakes, but I do see some things in your posted code 
that I don't think are optimal and might be related... they are:

1) You seem to be calling StartInternalThread() and 
WaitForInternalThreadToExit() on your Client object.  Shouldn't you be calling 
these methods on the =5FmessageTransceiverThread object, instead=3F   (Actually 
I would recommend calling ShutdownInternalThread() instead of 
WaitForInternalThreadToExit(), since that way the tell-thread-to-go-away-now 
step is done for you)

2) It appears that your Client class is a subclass of the MUSCLE Thread class.  
That means that in addition to the main() thread, each Client object spawns two 
threads -- one that is spawned by the StartInternalThread() call in 
Client::start(), and the thread that is held internally by the 
=5FmessageTransceiverThread object (I'm assuming you call 
=5FmessageTransceiverThread->StartInternalThread() somewhere).  Is this 
intentional=3F  In my experience you don't/shouldn't need a separate thread in 
addition to the MessageTransceiverThread, since all blocking operations already 
happen asynchronously, inside the MessageTransceiverThread object's internal 
thread.  (Maybe you have another reason for spawning an additional thread 

3) Your start() method uses a modal/blocking event loop, so that start() 
doesn't return until either the connection is complete or the connection times 
out.  This is sub-optimal since it means that your app is "tied up" inside 
start() until the method returns -- for example, if the user wants to quit the 
app, the app won't be able to quit until start() returns.  A better way to do 
the auto-reconnect logic is using the event-driven state-machine style -- in 
your main event loop, call the MessageTransceiverThread methods as necessary 
(they are all non-blocking), and handle the MessageTransceiverThread's 
connection-status-update events as they come in, without blocking in a separate 
event loop.   To implement the auto-reconnect logic, you could use a Win32 
timer technique such as WM=5FTIMER events.  Win32MessageTransceiverThread.h has 
several examples of this in the comments at the end of the file.

4) When all else fails, the tried-and-true debugging method for problems like 
this is to grep through the code for Win32 system calls that create or delete 
handles, and put a unique printf() next to each call.  (There are only a few 
files in the MUSCLE archive that call Win32 API calls, so this shouldn't be too 
difficult to do).  Then run the app with console output enabled (see 
MiscUtilityFunctions.cpp, lines 154-157 for code to open a console for stdout) 
and watch the output as the program runs.  Most likely you will see which call 
is creating handles on each connection attempt, and then it should be a simple 
matter to track down the matching free-handle call and figure out why it isn't 
being executed.


> We are using MUSCLE in a Windows XP environment. Our setup have a 
> "Teacher PC" which holds the server. This computer will connect to one 
> or more client "Student PC's" when the teacher want to start an 
> exercise. The computers often resides in different rooms, and are not 
> reachable for the teacher from where he sits. So for each exercise start 
> we want all the clients to connect automatically. Technically starting 
> the exercise means to start the server and connect the clients.
> Our current solution is that the clients will try to connect when they 
> start up, eventually give up after a timeout (for example 2 seconds), 
> and then try again. Like this they will connect automatically when the 
> server starts, and when the server stop they will go back to the "try to 
> connect" state.
> Problem is that after about 30 minutes with no connection (the teacher 
> is having lunch and have stopped the exercise for example) the client 
> hangs. Inspecting the task manager shows that the number of handles the 
> client application holds grows for each connection attempt (about 2 
> handles extra per attempt), and it seems that the application freezes 
> when it reaches about 10 000 handles.

Other related posts: