Imported Upstream version 5.0.0.42

Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-04-10 11:41:01 +00:00
parent 1190d13a04
commit 6bdd276d05
19939 changed files with 3099680 additions and 93811 deletions

View File

@ -140,52 +140,41 @@ namespace System.Net.Sockets
public void Complete ()
{
if (operation != SocketOperation.Receive && socket.is_disposed)
if (operation != SocketOperation.Receive && socket.CleanedUp)
DelayedException = new ObjectDisposedException (socket.GetType ().ToString ());
IsCompleted = true;
/* It is possible that this.socket is modified by this.Init which has been called by the callback. This
* would lead to inconsistency, as we would for example not release the correct socket.ReadSem or
* socket.WriteSem.
* For example, this can happen with AcceptAsync followed by a ReceiveAsync on the same
* SocketAsyncEventArgs */
Socket completedSocket = socket;
SocketOperation completedOperation = operation;
AsyncCallback callback = AsyncCallback;
if (callback != null) {
ThreadPool.UnsafeQueueUserWorkItem (_ => callback (this), null);
}
Queue<KeyValuePair<IntPtr, IOSelectorJob>> queue = null;
switch (operation) {
/* Warning: any field on the current SocketAsyncResult might have changed, as the callback might have
* called this.Init */
switch (completedOperation) {
case SocketOperation.Receive:
case SocketOperation.ReceiveFrom:
case SocketOperation.ReceiveGeneric:
case SocketOperation.Accept:
queue = socket.readQ;
completedSocket.ReadSem.Release ();
break;
case SocketOperation.Send:
case SocketOperation.SendTo:
case SocketOperation.SendGeneric:
queue = socket.writeQ;
completedSocket.WriteSem.Release ();
break;
}
if (queue != null) {
lock (queue) {
/* queue.Count will only be 0 if the socket is closed while receive/send/accept
* operation(s) are pending and at least one call to this method is waiting
* on the lock while another one calls CompleteAllOnDispose() */
if (queue.Count > 0)
queue.Dequeue (); /* remove ourselves */
if (queue.Count > 0) {
if (!socket.is_disposed) {
IOSelector.Add (queue.Peek ().Key, queue.Peek ().Value);
} else {
/* CompleteAllOnDispose */
KeyValuePair<IntPtr, IOSelectorJob> [] jobs = queue.ToArray ();
for (int i = 0; i < jobs.Length; i++)
ThreadPool.QueueUserWorkItem (j => ((IOSelectorJob) j).MarkDisposed (), jobs [i].Value);
queue.Clear ();
}
}
}
}
// IMPORTANT: 'callback', if any is scheduled from unmanaged code
}