[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void AllocateNativeOverlapped_PreAllocated_ReusedReturnedNativeOverlapped_OffsetLowAndOffsetHighSetToZero(bool useUnsafe)
    {
        // The CLR reuses NativeOverlapped underneath, check to make sure that they reset fields back to zero
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            PreAllocatedOverlapped preAlloc = useUnsafe ?
                                              PreAllocatedOverlapped.UnsafeCreate((_, __, ___) => { }, new object(), new byte[256]) :
                                              new PreAllocatedOverlapped((_, __, ___) => { }, new object(), new byte[256]);

            NativeOverlapped *overlapped = handle.AllocateNativeOverlapped(preAlloc);
            overlapped->OffsetHigh = 1;
            overlapped->OffsetLow  = 1;
            handle.FreeNativeOverlapped(overlapped);

            overlapped = handle.AllocateNativeOverlapped(preAlloc);

            Assert.Equal(IntPtr.Zero, overlapped->InternalLow);
            Assert.Equal(IntPtr.Zero, overlapped->InternalHigh);
            Assert.Equal(0, overlapped->OffsetLow);
            Assert.Equal(0, overlapped->OffsetHigh);
            Assert.Equal(IntPtr.Zero, overlapped->EventHandle);

            handle.FreeNativeOverlapped(overlapped);
        }
    }
예제 #2
0
        private Interop.HttpApi.HTTP_REQUEST *Allocate(ThreadPoolBoundHandle boundHandle, uint size)
        {
            uint newSize = size != 0 ? size : RequestBuffer == null ? 4096 : Size;

            if (_nativeOverlapped != null)
            {
#if DEBUG
                DebugRefCountReleaseNativeOverlapped();
#endif

                NativeOverlapped *nativeOverlapped = _nativeOverlapped;
                _nativeOverlapped = null;
                _boundHandle.FreeNativeOverlapped(nativeOverlapped);
            }

            if (_nativeOverlapped == null)
            {
#if DEBUG
                DebugRefCountAllocNativeOverlapped();
#endif
                SetBuffer(checked ((int)newSize));
                _boundHandle      = boundHandle;
                _nativeOverlapped = boundHandle.AllocateNativeOverlapped(ListenerAsyncResult.IOCallback, state: _result, pinData: RequestBuffer);
                return((Interop.HttpApi.HTTP_REQUEST *)Marshal.UnsafeAddrOfPinnedArrayElement(RequestBuffer, 0));
            }

            return(RequestBlob);
        }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void MultipleOperationsOverSingleHandle()
    {
        const int DATA_SIZE = 2;

        SafeHandle            handle      = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverSingleHandle.tmp"));
        ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle);

        OverlappedContext result1 = new OverlappedContext();
        OverlappedContext result2 = new OverlappedContext();

        byte[] data1 = new byte[DATA_SIZE];
        data1[0] = (byte)'A';
        data1[1] = (byte)'B';


        byte[] data2 = new byte[DATA_SIZE];
        data2[0] = (byte)'C';
        data2[1] = (byte)'D';

        NativeOverlapped *overlapped1 = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result1, data1);
        NativeOverlapped *overlapped2 = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result2, data2);

        fixed(byte *p1 = data1, p2 = data2)
        {
            int retval = DllImport.WriteFile(boundHandle.Handle, p1, DATA_SIZE, IntPtr.Zero, overlapped1);

            if (retval == 0)
            {
                Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error());
            }


            // Start the offset after the above write, so that it doesn't overwrite the previous write
            overlapped2->OffsetLow = DATA_SIZE;
            retval = DllImport.WriteFile(boundHandle.Handle, p2, DATA_SIZE, IntPtr.Zero, overlapped2);

            if (retval == 0)
            {
                Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error());
            }

            // Wait for overlapped operations to complete
            WaitHandle.WaitAll(new WaitHandle[] { result1.Event, result2.Event });
        }

        boundHandle.FreeNativeOverlapped(overlapped1);
        boundHandle.FreeNativeOverlapped(overlapped2);
        boundHandle.Dispose();
        handle.Dispose();

        Assert.Equal(0, result1.ErrorCode);
        Assert.Equal(0, result2.ErrorCode);
        Assert.Equal(DATA_SIZE, result1.BytesWritten);
        Assert.Equal(DATA_SIZE, result2.BytesWritten);
    }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void AllocateNativeOverlapped_NullAsContext_DoesNotThrow()
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[256]);
            Assert.True(result != null);
            handle.FreeNativeOverlapped(result);

            result = handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[256]);
            Assert.True(result != null);
            handle.FreeNativeOverlapped(result);
        }
    }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void AllocateNativeOverlapped_EmptyArrayAsPinData_DoesNotThrow()
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[0]);
            Assert.True(result != null);
            handle.FreeNativeOverlapped(result);

            result = handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[0]);
            Assert.True(result != null);
            handle.FreeNativeOverlapped(result);
        }
    }
예제 #6
0
        public void Complete(Exception exception, int transferred)
        {
            Debug.Assert(_overlapped != null);

            RegisteredSocket socket = _socket;

            _socket = null;
            _buffersHandle.Free();

            _boundHandle.FreeNativeOverlapped(_overlapped);
            _boundHandle   = null;
            _overlapped    = null;
            _thisRef.Value = null;

            if (exception == null)
            {
                _valueTaskSource.SetResult(transferred);
            }
            else
            {
                _valueTaskSource.SetException(exception);
            }

            Interlocked.Exchange(ref _isSend ? ref socket._cachedSendArgs : ref socket._cachedRecvArgs, this);
        }
예제 #7
0
        private void FreeNativeOverlapped()
        {
            IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero);

            // Do not call free during AppDomain shutdown, there may be an outstanding operation.
            // Overlapped will take care calling free when the native callback completes.
            if (oldHandle != IntPtr.Zero && !Environment.HasShutdownStarted)
            {
                unsafe
                {
                    Debug.Assert(_safeCloseSocket != null, "m_SafeCloseSocket is null.");

                    ThreadPoolBoundHandle boundHandle = _safeCloseSocket.IOCPBoundHandle;
                    Debug.Assert(boundHandle != null, "SafeNativeOverlapped::ImmediatelyFreeNativeOverlapped - boundHandle is null");

                    if (boundHandle != null)
                    {
                        // FreeNativeOverlapped will be called even if boundHandle was previously disposed.
                        boundHandle.FreeNativeOverlapped((NativeOverlapped *)oldHandle);
                    }

#if DEBUG
                    _safeCloseSocket.Release();
#endif
                    _safeCloseSocket = null;
                }
            }
            return;
        }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void SingleOperationOverSingleHandle()
    {
        const int DATA_SIZE = 2;

        SafeHandle            handle      = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"SingleOverlappedOverSingleHandle.tmp"));
        ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle);

        OverlappedContext result = new OverlappedContext();

        byte[] data = new byte[DATA_SIZE];
        data[0] = (byte)'A';
        data[1] = (byte)'B';

        NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(OnOverlappedOperationCompleted, result, data);

        fixed(byte *p = data)
        {
            int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped);

            if (retval == 0)
            {
                Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error());
            }

            // Wait for overlapped operation to complete
            result.Event.WaitOne();
        }

        boundHandle.FreeNativeOverlapped(overlapped);
        boundHandle.Dispose();
        handle.Dispose();

        Assert.Equal(0, result.ErrorCode);
        Assert.Equal(DATA_SIZE, result.BytesWritten);
    }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void FreeNativeOverlapped_WhenDisposed_DoesNotThrow()
    {
        ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle();
        NativeOverlapped *    overlapped  = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]);

        boundHandle.Dispose();
        boundHandle.FreeNativeOverlapped(overlapped);
    }
 // Will be called from the base class upon InvokeCallback()
 protected override void Cleanup()
 {
     base.Cleanup();
     if (_pOverlapped != null)
     {
         _boundHandle.FreeNativeOverlapped(_pOverlapped);
     }
 }
 [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
 public unsafe void FreeNativeOverlapped_NullAsNativeOverlapped_ThrowsArgumentNullException()
 {
     using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
     {
         AssertExtensions.Throws <ArgumentNullException>("overlapped", () =>
         {
             handle.FreeNativeOverlapped((NativeOverlapped *)null);
         });
     }
 }
예제 #12
0
    public unsafe void AllocateNativeOverlapped_PossibleReusedReturnedNativeOverlapped_OffsetLowAndOffsetHighSetToZero()
    {   // The CLR reuses NativeOverlapped underneath, check to make sure that they reset fields back to zero
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *overlapped = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]);
            overlapped->OffsetHigh = 1;
            overlapped->OffsetLow  = 1;
            handle.FreeNativeOverlapped(overlapped);

            overlapped = handle.AllocateNativeOverlapped((errorCode, numBytes, overlap) => { }, new object(), new byte[256]);

            Assert.Equal(IntPtr.Zero, overlapped->InternalLow);
            Assert.Equal(IntPtr.Zero, overlapped->InternalHigh);
            Assert.Equal(0, overlapped->OffsetLow);
            Assert.Equal(0, overlapped->OffsetHigh);
            Assert.Equal(IntPtr.Zero, overlapped->EventHandle);

            handle.FreeNativeOverlapped(overlapped);
        }
    }
예제 #13
0
        internal void ReleaseResources()
        {
            _cancellationRegistration.Dispose();

            // NOTE: The cancellation must *NOT* be running at this point, or it may observe freed memory
            // (this is why we disposed the registration above)
            if (Overlapped != null)
            {
                _threadPoolBinding.FreeNativeOverlapped(Overlapped);
                _overlapped = null;
            }
        }
예제 #14
0
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void FlowsAsyncLocalsToCallback_PreAllocatedOverlapped(bool shouldFlow)
    {
        // Makes sure that we flow async locals to callback

        const int DATA_SIZE = 2;

        SafeHandle            handle      = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"AsyncLocal.tmp"));
        ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle);

        OverlappedContext context = new OverlappedContext();

        byte[] data = new byte[DATA_SIZE];

        AsyncLocal <int> asyncLocal = new AsyncLocal <int>();

        asyncLocal.Value = 10;

        int?result = null;
        IOCompletionCallback callback = (_, __, ___) => {
            result = asyncLocal.Value;
            OnOverlappedOperationCompleted(_, __, ___);
        };

        using (PreAllocatedOverlapped preAlloc = shouldFlow ?
                                                 new PreAllocatedOverlapped(callback, context, data) :
                                                 PreAllocatedOverlapped.UnsafeCreate(callback, context, data))
        {
            NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(preAlloc);

            fixed(byte *p = data)
            {
                int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped);

                if (retval == 0)
                {
                    Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastPInvokeError());
                }

                // Wait for overlapped operation to complete
                context.Event.WaitOne();
            }

            boundHandle.FreeNativeOverlapped(overlapped);
        }

        boundHandle.Dispose();
        handle.Dispose();

        Assert.Equal(
            shouldFlow ? 10 : 0,
            result);
    }
예제 #15
0
 internal void Reset(uint size)
 {
     if (size == _size)
     {
         return;
     }
     if (_size != 0)
     {
         _boundHandle.FreeNativeOverlapped(_pOverlapped);
     }
     _size = size;
     if (size == 0)
     {
         _pOverlapped   = null;
         _memoryBlob    = null;
         _backingBuffer = null;
         return;
     }
     _backingBuffer = new byte[checked ((int)size)];
     _pOverlapped   = _boundHandle.AllocateNativeOverlapped(s_IOCallback, state: this, pinData: _backingBuffer);
     _memoryBlob    = (Interop.HttpApi.HTTP_SSL_CLIENT_CERT_INFO *)Marshal.UnsafeAddrOfPinnedArrayElement(_backingBuffer, 0);
 }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void AllocateNativeOverlapped_ObjectArrayAsPinData_DoesNotThrow()
    {
        var array = new object[]
        {
            new BlittableType()
            {
                i = 1
            },
            new byte[5],
        };

        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), array);
            Assert.True(result != null);
            handle.FreeNativeOverlapped(result);

            result = handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, new object(), array);
            Assert.True(result != null);
            handle.FreeNativeOverlapped(result);
        }
    }
예제 #17
0
    public unsafe void AllocateNativeOverlapped_BlittableTypeAsPinData_DoesNotThrow()
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *result = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new BlittableType()
            {
                i = 42
            });

            Assert.True(result != null);

            handle.FreeNativeOverlapped(result);
        }
    }
            internal void ReleaseNativeResource()
            {
                // Ensure that cancellation has been completed and cleaned up
                _cancellationRegistration.Dispose();

                // Free the overlapped
                // NOTE: The cancellation must *NOT* be running at this point, or it may observe freed memory
                // (this is why we disposed the registration above)
                if (_overlapped != null)
                {
                    _handle.FreeNativeOverlapped(_overlapped);
                    _overlapped = null;
                }
            }
예제 #19
0
        private Interop.HttpApi.HTTP_REQUEST *Allocate(ThreadPoolBoundHandle boundHandle, uint size)
        {
            uint newSize = size != 0 ? size : RequestBuffer == IntPtr.Zero ? 4096 : Size;

            if (_nativeOverlapped != null)
            {
#if DEBUG
                DebugRefCountReleaseNativeOverlapped();
#endif

                NativeOverlapped *nativeOverlapped = _nativeOverlapped;
                _nativeOverlapped = null;
                _boundHandle.FreeNativeOverlapped(nativeOverlapped);
            }

#if DEBUG
            DebugRefCountAllocNativeOverlapped();
#endif
            SetBuffer(checked ((int)newSize));
            _boundHandle      = boundHandle;
            _nativeOverlapped = boundHandle.AllocateNativeOverlapped(ListenerAsyncResult.IOCallback, state: _result, pinData: RequestBuffer);

            return((Interop.HttpApi.HTTP_REQUEST *)RequestBuffer.ToPointer());
        }
예제 #20
0
    public unsafe void AllocateNativeOverlapped_ReturnedNativeOverlapped_AllFieldsZero()
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *overlapped = handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]);

            Assert.Equal(IntPtr.Zero, overlapped->InternalLow);
            Assert.Equal(IntPtr.Zero, overlapped->InternalHigh);
            Assert.Equal(0, overlapped->OffsetLow);
            Assert.Equal(0, overlapped->OffsetHigh);
            Assert.Equal(IntPtr.Zero, overlapped->EventHandle);

            handle.FreeNativeOverlapped(overlapped);
        }
    }
        protected override bool ReleaseHandle()
        {
            IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero);

            // Do not call free durring AppDomain shutdown, there may be an outstanding operation.
            // Overlapped will take care calling free when the native callback completes.
            if (oldHandle != IntPtr.Zero && !NclUtilities.HasShutdownStarted)
            {
                unsafe
                {
                    _boundHandle.FreeNativeOverlapped((NativeOverlapped *)oldHandle);
                }
            }
            return(true);
        }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void AllocateNativeOverlapped_PreAllocated_WhenAlreadyAllocated_ThrowsArgumentException(bool useUnsafe)
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            using PreAllocatedOverlapped preAlloc = useUnsafe ?
                                                    PreAllocatedOverlapped.UnsafeCreate(delegate { }, null, null) :
                                                    new PreAllocatedOverlapped(delegate { }, null, null);

            NativeOverlapped *overlapped = handle.AllocateNativeOverlapped(preAlloc);

            AssertExtensions.Throws <ArgumentException>("preAllocated", () => handle.AllocateNativeOverlapped(preAlloc));

            handle.FreeNativeOverlapped(overlapped);
        }
    }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsNull_ReturnsNull()
    {
        using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath()))
        {
            using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle))
            {
                NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[0]);

                object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped);

                Assert.Null(result);

                boundHandle.FreeNativeOverlapped(overlapped);
            }
        }
    }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void FreeNativeOverlapped_WithWrongHandle_ThrowsArgumentException()
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            NativeOverlapped *overlapped = handle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, (byte[])null);

            using (ThreadPoolBoundHandle handle2 = CreateThreadPoolBoundHandle())
            {
                Assert.Throws <ArgumentException>(() =>
                {
                    handle2.FreeNativeOverlapped(overlapped);
                });
            }

            handle.FreeNativeOverlapped(overlapped);
        }
    }
예제 #25
0
    public unsafe void AllocateNativeOverlapped_PreAllocated_WhenAlreadyAllocated_ThrowsArgumentException()
    {
        using (ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle())
        {
            using (PreAllocatedOverlapped preAlloc = new PreAllocatedOverlapped(delegate { }, null, null))
            {
                NativeOverlapped *overlapped = handle.AllocateNativeOverlapped(preAlloc);

                Assert.Throws <ArgumentException>(() =>
                {
                    handle.AllocateNativeOverlapped(preAlloc);
                });

                handle.FreeNativeOverlapped(overlapped);
            }
        }
    }
예제 #26
0
        private unsafe void FreeNativeOverlapped()
        {
            // Do not call free during AppDomain shutdown, there may be an outstanding operation.
            // Overlapped will take care calling free when the native callback completes.
            IntPtr oldHandle = Interlocked.Exchange(ref handle, IntPtr.Zero);

            if (oldHandle != IntPtr.Zero && !Environment.HasShutdownStarted)
            {
                Debug.Assert(OperatingSystem.IsWindows());
                Debug.Assert(_socketHandle != null, "_socketHandle is null.");

                ThreadPoolBoundHandle?boundHandle = _socketHandle.IOCPBoundHandle;
                Debug.Assert(boundHandle != null, "SafeNativeOverlapped::FreeNativeOverlapped - boundHandle is null");

                // FreeNativeOverlapped will be called even if boundHandle was previously disposed.
                boundHandle?.FreeNativeOverlapped((NativeOverlapped *)oldHandle);
            }
        }
    public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsObject_ReturnsObject()
    {
        object context = new object();

        using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite())
        {
            using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle))
            {
                NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]);

                object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped);

                Assert.Same(context, result);

                boundHandle.FreeNativeOverlapped(overlapped);
            }
        }
    }
예제 #28
0
            // Method to clean up any existing Overlapped object and related state variables.
            private unsafe void FreeOverlapped(bool checkForShutdown)
            {
                if (!checkForShutdown || !Environment.HasShutdownStarted)
                {
                    // Free the overlapped object
                    if (_ptrNativeOverlapped != null)
                    {
                        _boundHandle.FreeNativeOverlapped(_ptrNativeOverlapped);
                        _ptrNativeOverlapped = null;
                    }

                    if (_dataChunksGCHandle.IsAllocated)
                    {
                        _dataChunksGCHandle.Free();
                        _dataChunks = null;
                    }
                }
            }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsIAsyncResult_ReturnsIAsyncResult()
    {                                         // CoreCLR/Desktop CLR version of overlapped sits on top of Overlapped class
        // and treats IAsyncResult specially, which is why we special case this case.

        AsyncResult context = new AsyncResult();

        using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath()))
        {
            using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle))
            {
                NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]);

                object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped);

                Assert.Same(context, result);

                boundHandle.FreeNativeOverlapped(overlapped);
            }
        }
    }
예제 #30
0
        unsafe private PipeStreamAsyncResult BeginWriteCore(byte[] buffer, int offset, int count,
                                                            AsyncCallback callback, Object state)
        {
            Debug.Assert(_handle != null, "_handle is null");
            Debug.Assert(!_handle.IsClosed, "_handle is closed");
            Debug.Assert(CanWrite, "can't write");
            Debug.Assert(buffer != null, "buffer == null");
            Debug.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
            Debug.Assert(offset >= 0, "offset is negative");
            Debug.Assert(count >= 0, "count is negative");

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

            asyncResult._userCallback    = callback;
            asyncResult._userStateObject = state;
            asyncResult._isWrite         = true;
            asyncResult._handle          = _handle;

            // fixed doesn't work well with zero length arrays. Set the zero-byte flag in case
            // caller needs to do any cleanup
            if (buffer.Length == 0)
            {
                //intOverlapped->InternalLow = IntPtr.Zero;

                // EndRead will free the Overlapped struct
                asyncResult.CallUserCallback();
            }
            else
            {
                // For Synchronous IO, I could go with either a userCallback and using the managed
                // Monitor class, or I could create a handle and wait on it.
                ManualResetEvent waitHandle = new ManualResetEvent(false);
                asyncResult._waitHandle = waitHandle;

                NativeOverlapped *intOverlapped = _threadPoolBinding.AllocateNativeOverlapped(s_IOCallback, asyncResult, buffer);
                asyncResult._overlapped = intOverlapped;

                int errorCode = 0;

                // Queue an async WriteFile operation and pass in a packed overlapped
                int r = WriteFileNative(_handle, buffer, offset, count, intOverlapped, out errorCode);

                // WriteFile, the OS version, will return 0 on failure, but this WriteFileNative
                // wrapper returns -1. This will return the following:
                // - On error, r==-1.
                // - On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
                // - On async requests that completed sequentially, r==0
                //
                // You will NEVER RELIABLY be able to get the number of buffer written back from this
                // call when using overlapped structures!  You must not pass in a non-null
                // lpNumBytesWritten to WriteFile when using overlapped structures!  This is by design
                // NT behavior.
                if (r == -1 && errorCode != Interop.mincore.Errors.ERROR_IO_PENDING)
                {
                    // Clean up
                    if (intOverlapped != null)
                    {
                        _threadPoolBinding.FreeNativeOverlapped(intOverlapped);
                    }
                    WinIOError(errorCode);
                }

                ReadWriteAsyncParams readWriteParams = state as ReadWriteAsyncParams;
                if (readWriteParams != null)
                {
                    if (readWriteParams.CancellationHelper != null)
                    {
                        readWriteParams.CancellationHelper.AllowCancellation(_handle, intOverlapped);
                    }
                }
            }

            return(asyncResult);
        }