beagle r4612 - in trunk/beagle: Util beagled



Author: dbera
Date: Tue Mar 18 03:02:29 2008
New Revision: 4612
URL: http://svn.gnome.org/viewvc/beagle?rev=4612&view=rev

Log:
Fix a deadlock diagnosed using bludgeon: UnixConnectionHandler:Close was not thread-safe but could be called from an async handler which runs in a thread. Also Network.BeginRead() could throw errors itself if the connection is already terminated; catch those exceptions.

Modified:
   trunk/beagle/Util/ExceptionHandlingThread.cs
   trunk/beagle/beagled/Server.cs

Modified: trunk/beagle/Util/ExceptionHandlingThread.cs
==============================================================================
--- trunk/beagle/Util/ExceptionHandlingThread.cs	(original)
+++ trunk/beagle/Util/ExceptionHandlingThread.cs	Tue Mar 18 03:02:29 2008
@@ -60,8 +60,8 @@
 			} catch (ThreadAbortException e) {
 				Logger.Log.Debug ("Thread aborted: {0}\n{1}\n", this.thread.Name, e.StackTrace);
 			} catch (Exception e) {
-				Logger.Log.Warn (e, "Exception caught while executing {0}:{1}",
-						 this.method.Target, this.method.Method);
+				Logger.Log.Warn (e, "Exception caught in {2} while executing {0}:{1}",
+						 this.method.Target, this.method.Method, this.thread.Name);
 			}
 
 			lock (live_threads)

Modified: trunk/beagle/beagled/Server.cs
==============================================================================
--- trunk/beagle/beagled/Server.cs	(original)
+++ trunk/beagle/beagled/Server.cs	Tue Mar 18 03:02:29 2008
@@ -409,6 +409,8 @@
 			Shutdown.WorkerFinished (network_data);
 		}
 
+		private bool closed = false;
+
 		public override void Close ()
 		{
 			CancelIfBlocking ();
@@ -417,17 +419,24 @@
 			// grab the lock here and close the underlying
 			// UnixClient, or else we'd deadlock between here and
 			// the Read() in HandleConnection()
+
+			// Do this in a lock since Close() should be thread-safe (can be called from AsyncCallback handler)
 			lock (this.client_lock) {
+				if (closed)
+					return;
+
 				if (this.client != null) {
 					this.client.Close ();
 					this.client = null;
 				}
-			}
 
-			if (this.executor != null) {
-				this.executor.Cleanup ();
-				this.executor.AsyncResponseEvent -= OnAsyncResponse;
-				this.executor = null;
+				if (this.executor != null) {
+					this.executor.Cleanup ();
+					this.executor.AsyncResponseEvent -= OnAsyncResponse;
+					this.executor = null;
+				}
+
+			    closed = true;
 			}
 
 			Server.RunGC ();
@@ -439,8 +448,10 @@
 
 			try {
 				bytes_read = this.client.GetStream ().EndRead (ar);
-			} catch (SocketException) {
-			} catch (IOException) { }
+			} catch (IOException e) {
+				if (! (e.InnerException is SocketException))
+					throw e;
+			} catch (ObjectDisposedException) { }
 
 			if (bytes_read == 0)
 				Close ();
@@ -455,8 +466,26 @@
 				return;
 			}
 
-			this.client.GetStream ().BeginRead (new byte[1024], 0, 1024,
-							    new AsyncCallback (WatchCallback), null);
+			try {
+				this.client.GetStream ().BeginRead (new byte[1024], 0, 1024,
+								    new AsyncCallback (WatchCallback), null);
+			} catch (ObjectDisposedException) {
+				Log.Debug ("Network stream closed; closing connection at this end");
+				this.Close ();
+				return;
+			} catch (IOException e) {
+				if (e.InnerException is SocketException) {
+					Log.Debug (e.InnerException, "Socket exception while setting up watch");
+					this.Close ();
+					return;
+				} else
+					throw e;
+			} catch (System.ArgumentException e) {
+				// https://bugzilla.novell.com/show_bug.cgi?id=371923
+				Log.Debug (e, "Possibly socket is already closed");
+				this.Close ();
+				return;
+			}
 		}
 	}	
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]