From b96b00cb9d54fb729dd3f0f6c989026c3919f51c Mon Sep 17 00:00:00 2001 From: Gonzalo Paniagua Javier Date: Tue, 13 Sep 2011 00:01:38 -0400 Subject: [PATCH] Internal worker is kept while there is an ongoing operation When there is an ongoing operation we can't dispose the internal worker because it might be used by the IO threadpool. Fixes Novell bug #691076 and Xamarin bug #766. --- .../System.Net.Sockets/SocketAsyncEventArgs.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs index 774eddc17e5..bd9f574feff 100644 --- a/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs +++ b/mcs/class/System/System.Net.Sockets/SocketAsyncEventArgs.cs @@ -2,9 +2,10 @@ // // Authors: // Marek Habersack (mhabersack@novell.com) -// Gonzalo Paniagua Javier (gonzalo@novell.com) +// Gonzalo Paniagua Javier (gonzalo@xamarin.com) // // Copyright (c) 2008,2010 Novell, Inc. (http://www.novell.com) +// Copyright (c) 2011 Xamarin, Inc. (http://xamarin.com) // // @@ -37,6 +38,8 @@ namespace System.Net.Sockets { public class SocketAsyncEventArgs : EventArgs, IDisposable { + bool disposed; + int in_progress; internal Socket.Worker Worker; EndPoint remote_ep; #if MOONLIGHT || NET_4_0 @@ -147,7 +150,11 @@ namespace System.Net.Sockets void Dispose (bool disposing) { + disposed = true; + if (disposing) { + if (disposed || Interlocked.CompareExchange (ref in_progress, 0, 0) != 0) + return; if (Worker != null) { Worker.Dispose (); Worker = null; @@ -171,6 +178,10 @@ namespace System.Net.Sockets internal void SetLastOperation (SocketAsyncOperation op) { + if (disposed) + throw new ObjectDisposedException ("System.Net.Sockets.SocketAsyncEventArgs"); + if (Interlocked.Exchange (ref in_progress, 1) != 0) + throw new InvalidOperationException ("Operation already in progress"); LastOperation = op; } @@ -219,6 +230,8 @@ namespace System.Net.Sockets static void DispatcherCB (IAsyncResult ares) { SocketAsyncEventArgs args = (SocketAsyncEventArgs) ares.AsyncState; + if (Interlocked.Exchange (ref args.in_progress, 0) != 1) + throw new InvalidOperationException ("No operation in progress"); SocketAsyncOperation op = args.LastOperation; // Notes; // -SocketOperation.AcceptReceive not used in SocketAsyncEventArgs -- 2.25.1