diff options
author | Alexander Köplinger <alex.koeplinger@outlook.com> | 2015-12-21 16:33:14 +0300 |
---|---|---|
committer | Alexander Köplinger <alex.koeplinger@outlook.com> | 2015-12-21 16:33:14 +0300 |
commit | 672cc6819815b0206d3f685c7379e00de916cd4d (patch) | |
tree | 5c21c5fd4fe508d5509255475d229628f96c8f4e /mcs | |
parent | aaca175b4467ce44dcb8fd5260099148eb4e7284 (diff) |
[ServiceModel] Make TcpReplyChannel.OnClose thread-safe
We were seeing the following unhandled exception on Jenkins:
````
Unhandled exceptions:
1) MonoTests.System.ServiceModel.OperationContextTest.Current : System.NullReferenceException: Object reference not set to an instance of an object
at System.ServiceModel.Channels.NetTcp.TcpReplyChannel.OnClose (TimeSpan timeout) [0x00000] in /media/ssd/jenkins/workspace/test-mono-mainline/label/debian-armhf/mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs:141
at System.ServiceModel.Channels.CommunicationObject.Close (TimeSpan timeout) [0x0001c] in /media/ssd/jenkins/workspace/test-mono-mainline/label/debian-armhf/mcs/class/System.ServiceModel/System.ServiceModel.Channels/CommunicationObject.cs:140
at System.ServiceModel.Channels.CommunicationObject.Close () [0x00000] in /media/ssd/jenkins/workspace/test-mono-mainline/label/debian-armhf/mcs/class/System.ServiceModel/System.ServiceModel.Channels/CommunicationObject.cs:131
at System.ServiceModel.Dispatcher.ListenerLoopManager.TryReceiveRequestDone (IAsyncResult result) [0x00027] in /media/ssd/jenkins/workspace/test-mono-mainline/label/debian-armhf/mcs/class/System.ServiceModel/System.ServiceModel.Dispatcher/ChannelDispatcher.cs:583
```
This happens because multiple threads can call OnClose() and so `client` can be null.
Fixed this by taking code from HttpReplyChannel.OnClose which handled this already and also fixed the race condition there (the checks need to happen under a lock).
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs | 9 | ||||
-rw-r--r-- | mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs | 9 |
2 files changed, 15 insertions, 3 deletions
diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs index 03e7cad1f1c..098b622aa83 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs @@ -104,12 +104,15 @@ namespace System.ServiceModel.Channels.Http } bool close_started; + object close_lock = new object (); protected override void OnClose (TimeSpan timeout) { - if (close_started) - return; - close_started = true; + lock (close_lock) { + if (close_started) + return; + close_started = true; + } DateTime start = DateTime.Now; // FIXME: consider timeout diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs index f597167e9d1..b005ad6c18a 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs @@ -135,9 +135,18 @@ namespace System.ServiceModel.Channels.NetTcp { throw new NotImplementedException (); } + + bool close_started; + object close_lock = new object (); protected override void OnClose (TimeSpan timeout) { + lock (close_lock) { + if (close_started) + return; + close_started = true; + } + client.Close (); client = null; base.OnClose (timeout); |