private unsafe static void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
#if DEBUG
            GlobalLog.SetThreadSource(ThreadKinds.CompletionPort);
            using (GlobalLog.SetThreadKind(ThreadKinds.System)) {
#if TRAVE
                try
                {
#endif
#endif
            //
            // Create an Overlapped object out of the native pointer we're provided with.
            // (this will NOT free the unmanaged memory in the native overlapped structure)
            //
            Overlapped callbackOverlapped         = Overlapped.Unpack(nativeOverlapped);
            BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)callbackOverlapped.AsyncResult;
            Debug.Assert((IntPtr)nativeOverlapped == asyncResult.m_Cache.NativeOverlapped.DangerousGetHandle(), "Handle mismatch");

            // The AsyncResult must be cleared before the callback is called (i.e. before ExtractCache is called).
            // Not doing so leads to a leak where the pinned cached OverlappedData continues to point to the async result object,
            // which points to the Socket (as well as user data), which points to the OverlappedCache, preventing the OverlappedCache
            // finalizer from freeing the pinned OverlappedData.
            callbackOverlapped.AsyncResult = null;

            object returnObject = null;

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

            GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.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 = UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(
                            socket.SafeHandle,
                            asyncResult.m_Cache.NativeOverlapped,
                            out numBytes,
                            false,
                            out ignore);
                        if (!success)
                        {
                            socketError = (SocketError)Marshal.GetLastWin32Error();
                            GlobalLog.Assert(socketError != 0, "BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|socketError:0 numBytes:{1}", ValidationHelper.HashString(asyncResult), numBytes);
                        }

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

        catch (Exception exception)
        {
            if (!NclUtilities.IsFatal(exception))
            {
                GlobalLog.Assert("BaseOverlappedAsyncResult::CompletionPortCallback", "Exception in completion callback type:" + exception.GetType().ToString() + " message:" + exception.Message);
            }
            throw;
        }
#endif
        }
#endif
        }
예제 #2
0
        private unsafe static void CompletionPortCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
#if DEBUG
            GlobalLog.SetThreadSource(ThreadKinds.CompletionPort);
            using (GlobalLog.SetThreadKind(ThreadKinds.System)) {
#endif
            //
            // Create an Overlapped object out of the native pointer we're provided with.
            // (this will NOT free the unmanaged memory in the native overlapped structure)
            //
            Overlapped callbackOverlapped         = Overlapped.Unpack(nativeOverlapped);
            BaseOverlappedAsyncResult asyncResult = (BaseOverlappedAsyncResult)callbackOverlapped.AsyncResult;

            // The AsyncResult must be cleared before the callback is called (i.e. before ExtractCache is called).
            // Not doing so leads to a leak where the pinned cached OverlappedData continues to point to the async result object,
            // which points to the Socket (as well as user data), which points to the OverlappedCache, preventing the OverlappedCache
            // finalizer from freeing the pinned OverlappedData.
            callbackOverlapped.AsyncResult = null;

            object returnObject = null;

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

            GlobalLog.Print("BaseOverlappedAsyncResult#" + ValidationHelper.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)
            {
                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.
                        //
                        bool success = UnsafeNclNativeMethods.OSSOCK.WSAGetOverlappedResult(
                            socket.SafeHandle,
                            (IntPtr)nativeOverlapped,
                            out numBytes,
                            false,
                            IntPtr.Zero);

                        if (!success)
                        {
                            socketError = (SocketError)Marshal.GetLastWin32Error();
                            GlobalLog.Assert(socketError != 0, "BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|socketError:0 numBytes:{1}", ValidationHelper.HashString(asyncResult), numBytes);
                        }

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

            if (asyncResult.InternalPeekCompleted)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.AssertFormat("BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|asyncResult.IsCompleted", LoggingHash.HashString(asyncResult));
                }
                Debug.Fail("BaseOverlappedAsyncResult#" + LoggingHash.HashString(asyncResult) + "::CompletionPortCallback()|asyncResult.IsCompleted");
            }
            if (GlobalLog.IsEnabled)
            {
                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();
                            if (socketError == 0)
                            {
                                if (GlobalLog.IsEnabled)
                                {
                                    GlobalLog.AssertFormat("BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|socketError:0 numBytes:{1}", LoggingHash.HashString(asyncResult), numBytes);
                                }
                                Debug.Fail("BaseOverlappedAsyncResult#" + LoggingHash.HashString(asyncResult) + "::CompletionPortCallback()|socketError:0 numBytes:" + numBytes);
                            }
                        }

                        if (success)
                        {
                            if (GlobalLog.IsEnabled)
                            {
                                GlobalLog.AssertFormat("BaseOverlappedAsyncResult#{0}::CompletionPortCallback()|Unexpectedly succeeded. errorCode:{1} numBytes:{2}", LoggingHash.HashString(asyncResult), errorCode, numBytes);
                            }
                            Debug.Fail("BaseOverlappedAsyncResult#" + LoggingHash.HashString(asyncResult) + "::CompletionPortCallback()|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
        }