public void Dispose_CalledMultipleTimes_DoesNotThrow()
    {
        ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle();

        boundHandle.Dispose();
        boundHandle.Dispose();
    }
Example #2
0
 private void DisposeCore(bool disposing)
 {
     if (disposing)
     {
         _threadPoolBinding?.Dispose();
     }
 }
    [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);
    }
Example #4
0
 private void UninitializeAsyncHandle()
 {
     if (_threadPoolBinding != null)
     {
         _threadPoolBinding.Dispose();
     }
 }
Example #5
0
        public unsafe void CloseRequestQueueHandle()
        {
            lock (this)
            {
                if (!RequestQueueHandle.IsInvalid)
                {
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Info($"Dispose ThreadPoolBoundHandle: {_requestQueueBoundHandle}");
                    }
                    _requestQueueBoundHandle?.Dispose();
                    RequestQueueHandle.Dispose();

                    // CancelIoEx is called after Dispose to prevent a race condition involving parallel GetContext and
                    // HttpReceiveHttpRequest calls. Otherwise, calling CancelIoEx before Dispose might block the synchronous
                    // GetContext call until the next request arrives.
                    try
                    {
                        Interop.Kernel32.CancelIoEx(RequestQueueHandle, null); // This cancels the synchronous call to HttpReceiveHttpRequest
                    }
                    catch (ObjectDisposedException)
                    {
                        // Ignore the exception since it only means that the queue handle has been successfully disposed
                    }
                }
            }
        }
    [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);
    }
    public unsafe void Dispose_WithoutFreeingNativeOverlapped_DoesNotThrow()
    {
        ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle();

        NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[1024]);

        boundHandle.Dispose();
    }
Example #8
0
            public void Dispose()
            {
                FileHandle.Dispose();

                ThreadPoolBoundHandle.Dispose();

                PreAllocatedOverlapped.Dispose();
            }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void AllocateNativeOverlapped_WhenDisposed_ThrowsObjectDisposedException()
    {
        ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle();

        handle.Dispose();

        Assert.Throws <ObjectDisposedException>(() => handle.AllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]));
        Assert.Throws <ObjectDisposedException>(() => handle.UnsafeAllocateNativeOverlapped((_, __, ___) => { }, new object(), new byte[256]));
    }
Example #10
0
    public void Handle_AfterDisposed_DoesNotThrow()
    {
        using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite())
        {
            ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle(handle);
            boundHandle.Dispose();

            Assert.Same(boundHandle.Handle, handle);
        }
    }
    public void Dispose_DoesNotDisposeHandle()
    {
        ThreadPoolBoundHandle boundHandle = CreateThreadPoolBoundHandle();

        Assert.False(boundHandle.Handle.IsClosed);

        boundHandle.Dispose();

        Assert.False(boundHandle.Handle.IsClosed);
    }
    [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_PreAllocated_WhenHandleDisposed_ThrowsObjectDisposedException(bool useUnsafe)
    {
        ThreadPoolBoundHandle handle = CreateThreadPoolBoundHandle();

        handle.Dispose();

        PreAllocatedOverlapped preAlloc = useUnsafe ?
                                          PreAllocatedOverlapped.UnsafeCreate(delegate { }, null, null) :
                                          new PreAllocatedOverlapped(delegate { }, null, null);

        Assert.Throws <ObjectDisposedException>(() => handle.AllocateNativeOverlapped(preAlloc));
    }
Example #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);
    }
    [PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix
    public unsafe void MultipleOperationsOverMultipleHandles()
    {
        const int DATA_SIZE = 2;

        SafeHandle            handle1      = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverMultipleHandle1.tmp"));
        SafeHandle            handle2      = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverMultipleHandle2.tmp"));
        ThreadPoolBoundHandle boundHandle1 = ThreadPoolBoundHandle.BindHandle(handle1);
        ThreadPoolBoundHandle boundHandle2 = ThreadPoolBoundHandle.BindHandle(handle2);

        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';

        PreAllocatedOverlapped preAlloc1 = new PreAllocatedOverlapped(OnOverlappedOperationCompleted, result1, data1);
        PreAllocatedOverlapped preAlloc2 = new PreAllocatedOverlapped(OnOverlappedOperationCompleted, result2, data2);

        for (int i = 0; i < 10; i++)
        {
            NativeOverlapped *overlapped1 = boundHandle1.AllocateNativeOverlapped(preAlloc1);
            NativeOverlapped *overlapped2 = boundHandle2.AllocateNativeOverlapped(preAlloc2);

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

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


                retval = DllImport.WriteFile(boundHandle2.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 });
            }

            boundHandle1.FreeNativeOverlapped(overlapped1);
            boundHandle2.FreeNativeOverlapped(overlapped2);

            result1.Event.Reset();
            result2.Event.Reset();

            Assert.Equal(0, result1.ErrorCode);
            Assert.Equal(0, result2.ErrorCode);
            Assert.Equal(DATA_SIZE, result1.BytesWritten);
            Assert.Equal(DATA_SIZE, result2.BytesWritten);
        }

        boundHandle1.Dispose();
        boundHandle2.Dispose();
        preAlloc1.Dispose();
        preAlloc2.Dispose();
        handle1.Dispose();
        handle2.Dispose();
    }