[Mono-devel-list] Re: [Mono-patches] r44192 - trunk/mcs/class/System/System.Net.Sockets

Dick Porter dick at ximian.com
Mon May 9 04:07:59 EDT 2005


On Sat, 2005-05-07 at 02:22 -0400, Gonzalo Paniagua wrote:
> Modified:
>    trunk/mcs/class/System/System.Net.Sockets/ChangeLog
>    trunk/mcs/class/System/System.Net.Sockets/Socket.cs
> Log:
> 2005-05-07 Gonzalo Paniagua Javier <gonzalo at ximian.com>
> 
> 	* Socket.cs: see bug #74842, which is fixed with this patch for details
> 	and test cases on the blocking behavior of accept() when close() is
> 	called from another thread. The solution applied is to Abort the thread
> 	that is blocking in Accept_internal() when someone calls Close (), then
> 	reset the abort state if the socket is disposed and return the same
> 	error as MS (10004 - interrupted).
> 

> Modified: trunk/mcs/class/System/System.Net.Sockets/Socket.cs
> ===================================================================
> --- trunk/mcs/class/System/System.Net.Sockets/Socket.cs	2005-05-07 05:22:49 UTC (rev 44191)
> +++ trunk/mcs/class/System/System.Net.Sockets/Socket.cs	2005-05-07 06:22:46 UTC (rev 44192)
> @@ -777,13 +777,25 @@
>  		[MethodImplAttribute(MethodImplOptions.InternalCall)]
>  		private extern static IntPtr Accept_internal(IntPtr sock,
>  							     out int error);
> -		
> +
> +		Thread accept_thread;
>  		public Socket Accept() {
>  			if (disposed && closed)
>  				throw new ObjectDisposedException (GetType ().ToString ());
>  
> -			int error;
> -			IntPtr sock=Accept_internal(socket, out error);
> +			int error = 0;
> +			IntPtr sock = (IntPtr) (-1);
> +			accept_thread = Thread.CurrentThread;
> +			try {
> +				sock = Accept_internal(socket, out error);
> +			} catch (ThreadAbortException the) {
> +				if (disposed) {
> +					Thread.ResetAbort ();
> +					error = 10004;
> +				}
> +			} finally {
> +				accept_thread = null;
> +			}
>  
>  			if (error != 0) {
>  				throw new SocketException (error);
> @@ -1715,6 +1727,10 @@
>  				IntPtr x = socket;
>  				socket = (IntPtr) (-1);
>  				Close_internal (x, out error);
> +				if (accept_thread != null) {
> +					accept_thread.Abort ();
> +					accept_thread = null;
> +				}
>  

Isn't it possible for the accept_thread to be aborted while it is in the
finally block?  Or Close()d multiple times while accept_thread != null?

Given how fragile thread aborting is, even without this race condition
this might get ugly.  I can't think of a better solution offhand
though...

- Dick






More information about the Mono-devel-list mailing list