[ServiceModel] Make TcpReplyChannel.OnClose thread-safe
authorAlexander Köplinger <alex.koeplinger@outlook.com>
Mon, 21 Dec 2015 13:33:14 +0000 (14:33 +0100)
committerAlexander Köplinger <alex.koeplinger@outlook.com>
Mon, 21 Dec 2015 13:33:14 +0000 (14:33 +0100)
commit672cc6819815b0206d3f685c7379e00de916cd4d
tree5c21c5fd4fe508d5509255475d229628f96c8f4e
parentaaca175b4467ce44dcb8fd5260099148eb4e7284
[ServiceModel] Make TcpReplyChannel.OnClose thread-safe

We were seeing the following unhandled exception on Jenkins:

````\rUnhandled 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).
mcs/class/System.ServiceModel/System.ServiceModel.Channels.Http/HttpReplyChannel.cs
mcs/class/System.ServiceModel/System.ServiceModel.Channels.NetTcp/TcpReplyChannel.cs