[mono/monodevelop] 1ad55564: [VersionControl] Never invoke VCS queries with the lock held

"Alan McGovern ([email protected])" <[email protected]>
Newsgroups gmane.comp.gnome.mono.patches
Message-ID <00000141e3306ffc-87998258-89c4-4bcf-92e6-e179b4fe2e6d-000000@email.amazonses.com>
   Branch: refs/heads/master
     Home: https://github.com/mono/monodevelop
  Compare: https://github.com/mono/monodevelop/compare/703e63cbe76d...1ad55564c3c4

   Commit: 1ad55564c3c489e725a83732b7dbb00d54929f5e
   Author: Alan McGovern <[email protected]> (alanmcgovern)
     Date: 2013-10-23 02:32:47 GMT
      URL: https://github.com/mono/monodevelop/commit/1ad55564c3c489e725a83732b7dbb00d54929f5e

[VersionControl] Never invoke VCS queries with the lock held

The purpose of this lock is purely to provide threadsafe access
to the collections holding the version control queries. We should
not execute any query with that lock held as that will result in
the IDE hanging until it has completely executed all VCS queries
in the current batch.

I kept the current intent of the code while respecting the semanatics
of the lock by duplicating the collections while the lock was held.

Changed paths:
  M main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs

Modified: main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/Repository.cs
===================================================================
@@ -292,23 +292,37 @@ void RunQueries (object ob)
 		//	DateTime t = DateTime.Now;
 		//	Console.WriteLine ("RunQueries started");
 			try {
-				lock (queryLock) {
-					var groups = fileQueryQueue.GroupBy (q => (q.QueryFlags & VersionInfoQueryFlags.IncludeRemoteStatus) != 0);
+				while (true) {
+					VersionInfoQuery [] fileQueryQueueClone;
+					DirectoryInfoQuery [] directoryQueryQueueClone;
+
+					lock (queryLock) {
+						if (fileQueryQueue.Count == 0 && directoryQueryQueue.Count == 0) {
+							queryRunning = false;
+							return;
+						}
+
+						fileQueryQueueClone = fileQueryQueue.ToArray ();
+						fileQueryQueue.Clear ();
+						filesInQueryQueue.Clear ();
+
+						directoryQueryQueueClone = directoryQueryQueue.ToArray ();
+						directoriesInQueryQueue.Clear ();
+						directoryQueryQueue.Clear ();
+					}
+
+					// Ensure we do not execute this with the query lock held, otherwise the IDE can hang while trying to add
+					// new queries to the queue while long-running VCS operations are being performed
+					var groups = fileQueryQueueClone.GroupBy (q => (q.QueryFlags & VersionInfoQueryFlags.IncludeRemoteStatus) != 0);
 					foreach (var group in groups) {
 						var status = OnGetVersionInfo (group.SelectMany (q => q.Paths), group.Key);
 						infoCache.SetStatus (status);
 					}
-					filesInQueryQueue.Clear ();
 
-					foreach (var item in directoryQueryQueue) {
+					foreach (var item in directoryQueryQueueClone) {
 						var status = OnGetDirectoryVersionInfo (item.Directory, item.GetRemoteStatus, false);
 						infoCache.SetDirectoryStatus (item.Directory, status, item.GetRemoteStatus);
 					}
-					directoriesInQueryQueue.Clear ();
-
-					fileQueryQueue.Clear ();
-					directoryQueryQueue.Clear ();
-					queryRunning = false;
 				}
 			} catch (Exception ex) {
 				LoggingService.LogError ("Version control status query failed", ex);


_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.