private static unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
#if DEBUG
            DebugThreadTracking.SetThreadSource(ThreadKinds.CompletionPort);
            using (DebugThreadTracking.SetThreadKind(ThreadKinds.System))
            {
#endif
            BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

            object returnObject = null;

            if (asyncResult.InternalPeekCompleted)
            {
                NetEventSource.Fail(null, $"asyncResult.IsCompleted: {asyncResult}");
            }
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(null, $"errorCode:{errorCode} numBytes:{numBytes} nativeOverlapped:{(IntPtr)nativeOverlapped}");
            }

            // Complete the IO and invoke the user's callback.
            SocketError socketError = (SocketError)errorCode;

            if (socketError != SocketError.Success && socketError != SocketError.OperationAborted)
            {
                // There are cases where passed errorCode does not reflect the details of the underlined socket error.
                // "So as of today, the key is the difference between WSAECONNRESET and ConnectionAborted,
                //  .e.g remote party or network causing the connection reset or something on the local host (e.g. closesocket
                // or receiving data after shutdown (SD_RECV)).  With Winsock/TCP stack rewrite in longhorn, there may
                // be other differences as well."

                Socket socket = asyncResult.AsyncObject as Socket;
                if (socket == null)
                {
                    socketError = SocketError.NotSocket;
                }
                else if (socket.CleanedUp)
                {
                    socketError = SocketError.OperationAborted;
                }
                else
                {
                    try
                    {
                        // The async IO completed with a failure.
                        // Here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
                        SocketFlags ignore;
                        bool        success = Interop.Winsock.WSAGetOverlappedResult(
                            socket.SafeHandle,
                            asyncResult.NativeOverlapped,
                            out numBytes,
                            false,
                            out ignore);
                        if (!success)
                        {
                            socketError = (SocketError)Marshal.GetLastWin32Error();
                            if (socketError == 0)
                            {
                                NetEventSource.Fail(asyncResult, $"socketError:0 numBytes:{numBytes}");
                            }
                        }
                        if (success)
                        {
                            NetEventSource.Fail(asyncResult, $"Unexpectedly succeeded. errorCode:{errorCode} numBytes:{numBytes}");
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // CleanedUp check above does not always work since this code is subject to race conditions
                        socketError = SocketError.OperationAborted;
                    }
                }
            }
            asyncResult.ErrorCode = (int)socketError;
            returnObject          = asyncResult.PostCompletion((int)numBytes);
            asyncResult.ReleaseUnmanagedStructures();
            asyncResult.InvokeCallback(returnObject);
#if DEBUG
        }
#endif
        }
Example #2
0
        private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
            ListenerClientCertAsyncResult asyncResult = (ListenerClientCertAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Info(null, $"errorCode:[{errorCode}] numBytes:[{numBytes}] nativeOverlapped:[{((long)nativeOverlapped)}]");
            }
            IOCompleted(asyncResult, errorCode, numBytes);
        }
    private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
    {
        var asyncResult = (ResponseStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped) !;

        IOCompleted(asyncResult, errorCode, numBytes);
    }
Example #4
0
        unsafe private static void AsyncPSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
        {
            // Extract async result from overlapped
            PipeStreamAsyncResult asyncResult = (PipeStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);

            asyncResult._numBytes = (int)numBytes;

            // Allow async read to finish
            if (!asyncResult._isWrite)
            {
                if (errorCode == Interop.mincore.Errors.ERROR_BROKEN_PIPE ||
                    errorCode == Interop.mincore.Errors.ERROR_PIPE_NOT_CONNECTED ||
                    errorCode == Interop.mincore.Errors.ERROR_NO_DATA)
                {
                    errorCode = 0;
                    numBytes  = 0;
                }
            }

            // For message type buffer.
            if (errorCode == Interop.mincore.Errors.ERROR_MORE_DATA)
            {
                errorCode = 0;
                asyncResult._isMessageComplete = false;
            }
            else
            {
                asyncResult._isMessageComplete = true;
            }

            asyncResult._errorCode = (int)errorCode;

            // Call the user-provided callback.  It can and often should
            // call EndRead or EndWrite.  There's no reason to use an async
            // delegate here - we're already on a threadpool thread.
            // IAsyncResult's completedSynchronously property must return
            // false here, saying the user callback was called on another thread.
            asyncResult._completedSynchronously = false;
            asyncResult._isComplete             = true;

            // The OS does not signal this event.  We must do it ourselves.
            ManualResetEvent wh = asyncResult._waitHandle;

            if (wh != null)
            {
                Debug.Assert(!wh.GetSafeWaitHandle().IsClosed, "ManualResetEvent already closed!");
                bool r = wh.Set();
                Debug.Assert(r, "ManualResetEvent::Set failed!");
                if (!r)
                {
                    throw Win32Marshal.GetExceptionForLastWin32Error();
                }
            }

            AsyncCallback callback = asyncResult._userCallback;

            if (callback != null)
            {
                callback(asyncResult);
            }
        }
        private unsafe IAsyncResult BeginWaitForConnection(AsyncCallback callback, Object state)
        {
            CheckConnectOperationsServerWithHandle();

            if (!IsAsync)
            {
                throw new InvalidOperationException(SR.InvalidOperation_PipeNotAsync);
            }

            // Create and store async stream class library specific data in the
            // async result
            PipeAsyncResult asyncResult = new PipeAsyncResult();

            asyncResult._threadPoolBinding = _threadPoolBinding;
            asyncResult._userCallback      = callback;
            asyncResult._userStateObject   = state;

            IOCancellationHelper cancellationHelper = state as IOCancellationHelper;

            // Create wait handle and store in async result
            ManualResetEvent waitHandle = new ManualResetEvent(false);

            asyncResult._waitHandle = waitHandle;

            NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped((errorCode, numBytes, pOverlapped) =>
            {
                // Unpack overlapped, free the pinned overlapped, and complete the operation
                PipeAsyncResult ar = (PipeAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);
                Debug.Assert(ar._overlapped == pOverlapped);
                ar._threadPoolBinding.FreeNativeOverlapped(pOverlapped);
                ar._overlapped = null;
                AsyncWaitForConnectionCallback(errorCode, numBytes, ar);
            }, asyncResult, null);

            asyncResult._overlapped = intOverlapped;

            if (!Interop.mincore.ConnectNamedPipe(InternalHandle, intOverlapped))
            {
                int errorCode = Marshal.GetLastWin32Error();

                if (errorCode == Interop.mincore.Errors.ERROR_IO_PENDING)
                {
                    if (cancellationHelper != null)
                    {
                        cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
                    }
                    return(asyncResult);
                }

                // WaitForConnectionCallback will not be called because we completed synchronously.
                // Either the pipe is already connected, or there was an error. Unpin and free the overlapped again.
                _threadPoolBinding.FreeNativeOverlapped(intOverlapped);
                asyncResult._overlapped = null;

                // Did the client already connect to us?
                if (errorCode == Interop.mincore.Errors.ERROR_PIPE_CONNECTED)
                {
                    if (State == PipeState.Connected)
                    {
                        throw new InvalidOperationException(SR.InvalidOperation_PipeAlreadyConnected);
                    }
                    asyncResult.CallUserCallback();
                    return(asyncResult);
                }

                throw Win32Marshal.GetExceptionForWin32Error(errorCode);
            }
            // will set state to Connected when EndWait is called
            if (cancellationHelper != null)
            {
                cancellationHelper.AllowCancellation(InternalHandle, intOverlapped);
            }

            return(asyncResult);
        }
            private static unsafe void Callback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
            {
                HttpRequestStreamAsyncResult asyncResult = (HttpRequestStreamAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, $"asyncResult: {asyncResult} errorCode:0x {errorCode.ToString("x8")} numBytes: {numBytes} nativeOverlapped:0x {((IntPtr)nativeOverlapped).ToString("x8")}");
                }

                IOCompleted(asyncResult, errorCode, numBytes);
            }
        private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
            ListenerAsyncResult asyncResult = (ListenerAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

            IOCompleted(asyncResult, errorCode, numBytes);
        }
Example #8
0
    private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
    {
        var asyncResult = (ClientCertLoader)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped) !;

        IOCompleted(asyncResult, errorCode, numBytes);
    }
            // When doing IO asynchronously (ie, _isAsync==true), this callback is
            // called by a free thread in the threadpool when the IO operation
            // completes.
            unsafe private static void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped *pOverlapped)
            {
                // Extract async result from overlapped
                FileStreamCompletionSource completionSource = (FileStreamCompletionSource)ThreadPoolBoundHandle.GetNativeOverlappedState(pOverlapped);

                Debug.Assert(completionSource._overlapped == pOverlapped, "Overlaps don't match");

                // Handle reading from & writing to closed pipes.  While I'm not sure
                // this is entirely necessary anymore, maybe it's possible for
                // an async read on a pipe to be issued and then the pipe is closed,
                // returning this error.  This may very well be necessary.
                ulong packedResult;

                if (errorCode != 0 && errorCode != Win32FileStream.ERROR_BROKEN_PIPE && errorCode != Win32FileStream.ERROR_NO_DATA)
                {
                    packedResult = ((ulong)ResultError | errorCode);
                }
                else
                {
                    packedResult = ((ulong)ResultSuccess | numBytes);
                }

                // Stow the result so that other threads can observe it
                // And, if no other thread is registering cancellation, continue
                if (NoResult == Interlocked.Exchange(ref completionSource._result, (long)packedResult))
                {
                    // Successfully set the state, attempt to take back the callback
                    if (Interlocked.Exchange(ref completionSource._result, CompletedCallback) != NoResult)
                    {
                        // Successfully got the callback, finish the callback
                        completionSource.CompleteCallback(packedResult);
                    }
                    // else: Some other thread stole the result, so now it is responsible to finish the callback
                }
                // else: Some other thread is registering a cancellation, so it *must* finish the callback
            }
Example #10
0
        /// <summary>Start monitoring the current directory.</summary>
        private void StartRaisingEvents()
        {
            // If we're called when "Initializing" is true, set enabled to true
            if (IsSuspended())
            {
                _enabled = true;
                return;
            }

            // If we're already running, don't do anything.
            if (!IsHandleInvalid(_directoryHandle))
            {
                return;
            }

            // Create handle to directory being monitored
            _directoryHandle = Interop.Kernel32.CreateFile(
                lpFileName: _directory,
                dwDesiredAccess: Interop.Kernel32.FileOperations.FILE_LIST_DIRECTORY,
                dwShareMode: FileShare.Read | FileShare.Delete | FileShare.Write,
                dwCreationDisposition: FileMode.Open,
                dwFlagsAndAttributes: Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS | Interop.Kernel32.FileOperations.FILE_FLAG_OVERLAPPED);

            if (IsHandleInvalid(_directoryHandle))
            {
                _directoryHandle = null;
                throw new FileNotFoundException(SR.Format(SR.FSW_IOError, _directory));
            }

            // Create the state associated with the operation of monitoring the direction
            AsyncReadState state;

            try
            {
                // Start ignoring all events that were initiated before this, and
                // allocate the buffer to be pinned and used for the duration of the operation
                int    session = Interlocked.Increment(ref _currentSession);
                byte[] buffer  = AllocateBuffer();

                // Store all state, including a preallocated overlapped, into the state object that'll be
                // passed from iteration to iteration during the lifetime of the operation.  The buffer will be pinned
                // from now until the end of the operation.
                state = new AsyncReadState(session, buffer, _directoryHandle, ThreadPoolBoundHandle.BindHandle(_directoryHandle), this);
                unsafe
                {
                    state.PreAllocatedOverlapped = new PreAllocatedOverlapped((errorCode, numBytes, overlappedPointer) =>
                    {
                        AsyncReadState state = (AsyncReadState)ThreadPoolBoundHandle.GetNativeOverlappedState(overlappedPointer) !;
                        state.ThreadPoolBinding.FreeNativeOverlapped(overlappedPointer);
                        if (state.WeakWatcher.TryGetTarget(out FileSystemWatcher? watcher))
                        {
                            watcher.ReadDirectoryChangesCallback(errorCode, numBytes, state);
                        }
                    }, state, buffer);
                }
            }
            catch
            {
                // Make sure we don't leave a valid directory handle set if we're not running
                _directoryHandle.Dispose();
                _directoryHandle = null;
                throw;
            }

            // Start monitoring
            _enabled = true;
            Monitor(state);
        }
        /// <devdoc>
        ///     Callback from thread pool.
        /// </devdoc>
        /// <internalonly/>
        private unsafe void CompletionStatusChanged(uint errorCode, uint numBytes, NativeOverlapped *overlappedPointer)
        {
            FSWAsyncResult asyncResult = (FSWAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(overlappedPointer);

            try
            {
                if (_stopListening)
                {
                    return;
                }

                lock (this)
                {
                    if (errorCode != 0)
                    {
                        if (errorCode == 995 /* ERROR_OPERATION_ABORTED */)
                        {
                            //Inside a service the first completion status is false
                            //cannot return without monitoring again.
                            //Because this return statement is inside a try/finally block,
                            //the finally block will execute. It does restart the monitoring.
                            return;
                        }
                        else
                        {
                            OnError(new ErrorEventArgs(new Win32Exception((int)errorCode)));
                            EnableRaisingEvents = false;
                            return;
                        }
                    }

                    // Ignore any events that occurred before this "session",
                    // so we don't get changed or error events after we
                    // told FSW to stop.
                    if (asyncResult.session != _currentSession)
                    {
                        return;
                    }


                    if (numBytes == 0)
                    {
                        NotifyInternalBufferOverflowEvent();
                    }
                    else
                    {  // Else, parse each of them and notify appropriate delegates
                       /******
                        *  Format for the buffer is the following C struct:
                        *
                        *  typedef struct _FILE_NOTIFY_INFORMATION {
                        *     DWORD NextEntryOffset;
                        *     DWORD Action;
                        *     DWORD FileNameLength;
                        *     WCHAR FileName[1];
                        *  } FILE_NOTIFY_INFORMATION;
                        *
                        *  NOTE1: FileNameLength is length in bytes.
                        *  NOTE2: The Filename is a Unicode string that's NOT NULL terminated.
                        *  NOTE3: A NextEntryOffset of zero means that it's the last entry
                        *******/

                        // Parse the file notify buffer:
                        int    offset = 0;
                        int    nextOffset, action, nameLength;
                        string oldName = null;
                        string name    = null;

                        do
                        {
                            fixed(byte *buffPtr = asyncResult.buffer)
                            {
                                // Get next offset:
                                nextOffset = *((int *)(buffPtr + offset));

                                // Get change flag:
                                action = *((int *)(buffPtr + offset + 4));

                                // Get filename length (in bytes):
                                nameLength = *((int *)(buffPtr + offset + 8));
                                name       = new string((char *)(buffPtr + offset + 12), 0, nameLength / 2);
                            }


                            /* A slightly convoluted piece of code follows.  Here's what's happening:
                             *
                             * We wish to collapse the poorly done rename notifications from the
                             * ReadDirectoryChangesW API into a nice rename event. So to do that,
                             * it's assumed that a FILE_ACTION_RENAMED_OLD_NAME will be followed
                             * immediately by a FILE_ACTION_RENAMED_NEW_NAME in the buffer, which is
                             * all that the following code is doing.
                             *
                             * On a FILE_ACTION_RENAMED_OLD_NAME, it asserts that no previous one existed
                             * and saves its name.  If there are no more events in the buffer, it'll
                             * assert and fire a RenameEventArgs with the Name field null.
                             *
                             * If a NEW_NAME action comes in with no previous OLD_NAME, we assert and fire
                             * a rename event with the OldName field null.
                             *
                             * If the OLD_NAME and NEW_NAME actions are indeed there one after the other,
                             * we'll fire the RenamedEventArgs normally and clear oldName.
                             *
                             * If the OLD_NAME is followed by another action, we assert and then fire the
                             * rename event with the Name field null and then fire the next action.
                             *
                             * In case it's not a OLD_NAME or NEW_NAME action, we just fire the event normally.
                             *
                             * (Phew!)
                             */

                            // If the action is RENAMED_FROM, save the name of the file
                            if (action == Direct.FILE_ACTION_RENAMED_OLD_NAME)
                            {
                                Debug.Assert(oldName == null, "FileSystemWatcher: Two FILE_ACTION_RENAMED_OLD_NAME " +
                                             "in a row!  [" + oldName + "], [ " + name + "]");

                                oldName = name;
                            }
                            else if (action == Direct.FILE_ACTION_RENAMED_NEW_NAME)
                            {
                                if (oldName != null)
                                {
                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
                                    oldName = null;
                                }
                                else
                                {
                                    Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_NEW_NAME with no" +
                                               "old name! [ " + name + "]");

                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, name, oldName);
                                    oldName = null;
                                }
                            }
                            else
                            {
                                if (oldName != null)
                                {
                                    Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
                                               "new name!  [" + oldName + "]");

                                    NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                                    oldName = null;
                                }

                                // Notify each file of change
                                NotifyFileSystemEventArgs(action, name);
                            }

                            offset += nextOffset;
                        } while (nextOffset != 0);

                        if (oldName != null)
                        {
                            Debug.Fail("FileSystemWatcher: FILE_ACTION_RENAMED_OLD_NAME with no" +
                                       "new name!  [" + oldName + "]");

                            NotifyRenameEventArgs(WatcherChangeTypes.Renamed, null, oldName);
                            oldName = null;
                        }
                    }
                }
            }
            finally
            {
                _threadPoolBinding.FreeNativeOverlapped(overlappedPointer);
                if (!_stopListening)
                {
                    Monitor(asyncResult.buffer);
                }
            }
        }
Example #12
0
        private static unsafe void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
            Debug.Assert(OperatingSystem.IsWindows());
            BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped) !;

            if (asyncResult.InternalPeekCompleted)
            {
                NetEventSource.Fail(null, $"asyncResult.IsCompleted: {asyncResult}");
            }
            if (NetEventSource.Log.IsEnabled())
            {
                NetEventSource.Info(null, $"errorCode:{errorCode} numBytes:{numBytes} nativeOverlapped:{(IntPtr)nativeOverlapped}");
            }

            // Complete the IO and invoke the user's callback.
            SocketError socketError = (SocketError)errorCode;

            if (socketError != SocketError.Success && socketError != SocketError.OperationAborted)
            {
                // There are cases where passed errorCode does not reflect the details of the underlined socket error.
                // "So as of today, the key is the difference between WSAECONNRESET and ConnectionAborted,
                //  .e.g remote party or network causing the connection reset or something on the local host (e.g. closesocket
                // or receiving data after shutdown (SD_RECV)).  With Winsock/TCP stack rewrite in longhorn, there may
                // be other differences as well."

                Socket?socket = asyncResult.AsyncObject as Socket;
                if (socket == null)
                {
                    socketError = SocketError.NotSocket;
                }
                else if (socket.Disposed)
                {
                    socketError = SocketError.OperationAborted;
                }
                else
                {
                    try
                    {
                        // The async IO completed with a failure.
                        // Here we need to call WSAGetOverlappedResult() just so GetLastSocketError() will return the correct error.
                        SocketFlags ignore;
                        bool        success = Interop.Winsock.WSAGetOverlappedResult(
                            socket.SafeHandle,
                            nativeOverlapped,
                            out numBytes,
                            false,
                            out ignore);
                        if (!success)
                        {
                            socketError = SocketPal.GetLastSocketError();
                        }
                        if (success)
                        {
                            NetEventSource.Fail(asyncResult, $"Unexpectedly succeeded. errorCode:{errorCode} numBytes:{numBytes}");
                        }
                    }
                    catch (ObjectDisposedException)
                    {
                        // Disposed check above does not always work since this code is subject to race conditions
                        socketError = SocketError.OperationAborted;
                    }
                }
            }

            // Set results and invoke callback
            asyncResult.CompletionCallback((int)numBytes, socketError);
        }
        private unsafe static void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
#if DEBUG
            GlobalLog.SetThreadSource(ThreadKinds.CompletionPort);
            using (GlobalLog.SetThreadKind(ThreadKinds.System))
            {
#endif
            BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

            object returnObject = null;

            GlobalLog.Assert(!asyncResult.InternalPeekCompleted, "BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|asyncResult.IsCompleted", LoggingHash.HashString(asyncResult));

            GlobalLog.Print(
                "BaseOverlappedAsyncResult#" + LoggingHash.HashString(asyncResult) + "::CompletionPortCallback" +
                " errorCode:" + errorCode.ToString() +
                " numBytes:" + numBytes.ToString() +
                " pOverlapped:" + ((int)nativeOverlapped).ToString());

            // Complete the IO and invoke the user's callback.
            SocketError socketError = (SocketError)errorCode;

            if (socketError != SocketError.Success && socketError != SocketError.OperationAborted)
            {
                // There are cases where passed errorCode does not reflect the details of the underlined socket error.
                // "So as of today, the key is the difference between WSAECONNRESET and ConnectionAborted,
                //  .e.g remote party or network causing the connection reset or something on the local host (e.g. closesocket
                // or receiving data after shutdown (SD_RECV)).  With Winsock/TCP stack rewrite in longhorn, there may
                // be other differences as well."

                Socket socket = asyncResult.AsyncObject as Socket;
                if (socket == null)
                {
                    socketError = SocketError.NotSocket;
                }
                else if (socket.CleanedUp)
                {
                    socketError = SocketError.OperationAborted;
                }
                else
                {
                    try
                    {
                        // The async IO completed with a failure.
                        // Here we need to call WSAGetOverlappedResult() just so Marshal.GetLastWin32Error() will return the correct error.
                        SocketFlags ignore;
                        bool        success = Interop.Winsock.WSAGetOverlappedResult(
                            socket.SafeHandle,
                            asyncResult.NativeOverlapped,
                            out numBytes,
                            false,
                            out ignore);
                        if (!success)
                        {
                            socketError = (SocketError)Marshal.GetLastWin32Error();
                            GlobalLog.Assert(socketError != 0, "BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|socketError:0 numBytes:{1}", LoggingHash.HashString(asyncResult), numBytes);
                        }

                        GlobalLog.Assert(!success, "BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|Unexpectedly succeeded. errorCode:{1} numBytes:{2}", LoggingHash.HashString(asyncResult), errorCode, numBytes);
                    }
                    catch (ObjectDisposedException)
                    {
                        // CleanedUp check above does not always work since this code is subject to race conditions
                        socketError = SocketError.OperationAborted;
                    }
                }
            }
            asyncResult.ErrorCode = (int)socketError;
            returnObject          = asyncResult.PostCompletion((int)numBytes);
            asyncResult.ReleaseUnmanagedStructures();
            asyncResult.InvokeCallback(returnObject);
#if DEBUG
        }
#endif
        }