[System.ServiceModel] Fix "collection was modified" exception in tests
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels.Http / HttpListenerManager.cs
index b3c3fe2c85d8ea26bdd2f7044c13936e6e1aa4c1..5ccee0a2605dfa6d5e968e426f232e0fcf9542fd 100644 (file)
@@ -48,24 +48,29 @@ namespace System.ServiceModel.Channels.Http
                        Entries = new List<HttpChannelListenerEntry> ();
                }
 
-               public List<HttpChannelListenerEntry> Entries { get; private set; }
+               protected List<HttpChannelListenerEntry> Entries { get; private set; }
+               object entries_lock = new object ();
 
                public abstract void RegisterListener (ChannelDispatcher channel, HttpTransportBindingElement element, TimeSpan timeout);
                public abstract void UnregisterListener (ChannelDispatcher channel, TimeSpan timeout);
 
                protected void RegisterListenerCommon (ChannelDispatcher channel, TimeSpan timeout)
                {
-                       Entries.Add (new HttpChannelListenerEntry (channel, new AutoResetEvent (false)));
+                       lock (entries_lock) {
+                               Entries.Add (new HttpChannelListenerEntry (channel, new AutoResetEvent (false)));
 
-                       Entries.Sort (HttpChannelListenerEntry.CompareEntries);
+                               Entries.Sort (HttpChannelListenerEntry.CompareEntries);
+                       }
                }
 
                protected void UnregisterListenerCommon (ChannelDispatcher channel, TimeSpan timeout)
                {
-                       var entry = Entries.First (e => e.ChannelDispatcher == channel);
-                       Entries.Remove (entry);
+                       lock (entries_lock) {
+                               var entry = Entries.First (e => e.ChannelDispatcher == channel);
+                               Entries.Remove (entry);
 
-                       entry.WaitHandle.Set (); // make sure to finish pending requests.
+                               entry.WaitHandle.Set (); // make sure to finish pending requests.
+                       }
                }
 
                public void ProcessNewContext (HttpContextInfo ctxi)
@@ -79,9 +84,11 @@ namespace System.ServiceModel.Channels.Http
 
                HttpChannelListenerEntry SelectChannel (HttpContextInfo ctx)
                {
-                       foreach (var e in Entries)
-                               if (e.FilterHttpContext (ctx))
-                                       return e;
+                       lock (entries_lock) {
+                               foreach (var e in Entries)
+                                       if (e.FilterHttpContext (ctx))
+                                               return e;
+                       }
                        return null;
                }
 
@@ -90,7 +97,10 @@ namespace System.ServiceModel.Channels.Http
                        DateTime start = DateTime.Now;
 
                        context = null;
-                       var ce = Entries.FirstOrDefault (e => e.ChannelDispatcher == channel);
+                       HttpChannelListenerEntry ce = null;
+                       lock (entries_lock) {
+                               ce = Entries.FirstOrDefault (e => e.ChannelDispatcher == channel);
+                       }
                        if (ce == null)
                                return false;
                        lock (ce.RetrieverLock) {