[Mono-dev] [PATCH] TcpChannel hang on Windows.

Bill Holmes billholmes54 at gmail.com
Wed Dec 17 15:03:10 EST 2008


Hi,

Over the past week I have been asking some of you how to correct a
hang on exit with TcpChannels on Windows.  To recap instantiating a
TcpChannel runs a background thread which calls Socket.Accept and
blocks.  During shutdown a call to mono_thread_manage executes an APC
on the waiting thread and then (mono_thread_manage) waits for the
blocking thread to exit.  The problem is that the APC call does not
cause the accept call to break.

There were a couple of suggestions about how to solve this problem.
Some were specific to accept and others were general patterns
'un-stick' blocking calls in the runtime.  I believe that have tried
them all.  Some did not work while others caused other complications.

The one I decided on was to call select with a timeout to determine if
a following accept call would succeed immediately.  Consider it a peek
on the socket.  If the select times out and no connection is present I
check the thread state for StopRequested. (Not Abort intentionally.)
Finally this is an a infinite loop until a connection is present or
the thread is stopped.  The loop is only applicable to Windows as I do
not observe a problem on Linux.

One thing that I had to change was the signature to the internal
accept call.  I need to know the blocking state of the socket.  If a
socket is in blocking mode I can go into the loop.  If the socket is
in non-blocking mode I can not use the loop because it will cause the
call to accept to block on a non-blocking socket.  The reason I have
to pass it into the internal call is because after much searching I
can not find a way to query the blocking state of a socket.  (There is
no ret = fcntl(fd, F_GETFL, 0); on Windows?)  If anyone knows how to
query this state let me know and I will be happy to change it.

-bill

2008-12-17  Bill Holmes  <billholmes54 at gmail.com>

	* Socket.cs (Accept_internal) :  Changing the signature to pass
	  the blocking state.

	* socket-io.h : Changing the signature of
	  ves_icall_System_Net_Sockets_Socket_Accept_internal to pass
	  the blocking state.

	* icall-def.h :  Changing the signature of
	  System.Net.Sockets.Socket.Accept_internal to pass the blocking state.

	* socket-io.c (ves_icall_System_Net_Sockets_Socket_Accept_internal) :
	  For Windows only.  Avoid blocking when calling accept by
	  querying for a connection via select.  The loop also queries
	  the thread state every 1000 micro seconds for the thread
	  stop state.  This will avoid the process hanging on shutdown
	  when using a TcpChannel that is never connected to.

	Code is contributed under MIT/X11 license.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sockcl.patch
Type: text/x-diff
Size: 6268 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20081217/c2fb1a50/attachment-0001.bin 


More information about the Mono-devel-list mailing list