public void FlushAsyncCancellationDeadlock()
        {
            var cts  = new CancellationTokenSource();
            var cts2 = new CancellationTokenSource();
            var e    = new ManualResetEventSlim();

            PipeAwaiter <ReadResult> awaiter = Pipe.Reader.ReadAsync(cts.Token);

            awaiter.OnCompleted(
                () => {
                // We are on cancellation thread and need to wait untill another ReadAsync call
                // takes pipe state lock
                e.Wait();
                // Make sure we had enough time to reach _cancellationTokenRegistration.Dispose
                Thread.Sleep(100);
                // Try to take pipe state lock
                Pipe.Reader.ReadAsync();
            });

            // Start a thread that would run cancellation calbacks
            Task cancellationTask = Task.Run(() => cts.Cancel());
            // Start a thread that would call ReadAsync with different token
            // and block on _cancellationTokenRegistration.Dispose
            Task blockingTask = Task.Run(
                () => {
                e.Set();
                Pipe.Reader.ReadAsync(cts2.Token);
            });

            bool completed = Task.WhenAll(cancellationTask, blockingTask).Wait(TimeSpan.FromSeconds(10));

            Assert.True(completed);
        }
        public void ReadAsyncReturnsIsCancelOnCancelPendingReadBeforeGetResult()
        {
            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(() => { });

            Pipe.Writer.WriteAsync(new byte[] { });
            Pipe.Reader.CancelPendingRead();

            Assert.True(awaitable.IsCompleted);

            ReadResult result = awaitable.GetResult();

            Assert.True(result.IsCanceled);
        }
Example #3
0
        public void FlushAsyncReturnsIsCancelOnCancelPendingFlushBeforeGetResult()
        {
            PipeWriter writableBuffer           = Pipe.Writer.WriteEmpty(MaximumSizeHigh);
            PipeAwaiter <FlushResult> awaitable = writableBuffer.FlushAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(() => { });

            Pipe.Reader.AdvanceTo(Pipe.Reader.ReadAsync().GetResult().Buffer.End);
            Pipe.Writer.CancelPendingFlush();

            Assert.True(awaitable.IsCompleted);

            FlushResult result = awaitable.GetResult();

            Assert.True(result.IsCanceled);
        }
        public void GetResultThrowsIfReadAsyncCanceledBeforeOnCompleted()
        {
            var onCompletedCalled       = false;
            var cancellationTokenSource = new CancellationTokenSource();

            PipeAwaiter <ReadResult> awaiter = Pipe.Reader.ReadAsync(cancellationTokenSource.Token);
            bool awaiterIsCompleted          = awaiter.IsCompleted;

            cancellationTokenSource.Cancel();

            awaiter.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.Throws <OperationCanceledException>(() => awaiter.GetResult());
            });

            Assert.False(awaiterIsCompleted);
            Assert.True(onCompletedCalled);
        }
        private async Task FlushAsyncAwaited(PipeAwaiter <FlushResult> awaitable, CancellationToken cancellationToken)
        {
            // https://github.com/dotnet/corefxlab/issues/1334
            // Since the flush awaitable doesn't currently support multiple awaiters
            // we need to use a task to track the callbacks.
            // All awaiters get the same task
            lock (_flushLock)
            {
                if (_flushTcs == null || _flushTcs.Task.IsCompleted)
                {
                    _flushTcs = new TaskCompletionSource <object>();

                    awaitable.OnCompleted(_flushCompleted);
                }
            }

            await _flushTcs.Task;

            cancellationToken.ThrowIfCancellationRequested();
        }
Example #6
0
        public void GetResultThrowsIfFlushAsyncCancelledBeforeOnCompleted()
        {
            var        onCompletedCalled       = false;
            var        cancellationTokenSource = new CancellationTokenSource();
            PipeWriter buffer = Pipe.Writer.WriteEmpty(MaximumSizeHigh);

            PipeAwaiter <FlushResult> awaiter = buffer.FlushAsync(cancellationTokenSource.Token);
            bool awaiterIsCompleted           = awaiter.IsCompleted;

            cancellationTokenSource.Cancel();

            awaiter.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.Throws <OperationCanceledException>(() => awaiter.GetResult());
            });

            Assert.False(awaiterIsCompleted);
            Assert.True(onCompletedCalled);
        }
        public void OnWriterCompletedRanBeforeReadContinuation()
        {
            var callbackRan     = false;
            var continuationRan = false;
            var pipe            = new Pipe(new PipeOptions(_pool));

            pipe.Reader.OnWriterCompleted(
                (exception, state) => {
                callbackRan = true;
                Assert.False(continuationRan);
            }, null);

            PipeAwaiter <ReadResult> awaiter = pipe.Reader.ReadAsync();

            Assert.False(awaiter.IsCompleted);
            awaiter.OnCompleted(() => { continuationRan = true; });
            pipe.Writer.Complete();

            Assert.True(callbackRan);
        }
        public void ReadAsyncNotCompletedAfterCancellationTokenCanceled()
        {
            var onCompletedCalled = false;
            var cts = new CancellationTokenSource();
            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync(cts.Token);

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.True(awaitable.IsCompleted);

                Assert.Throws <OperationCanceledException>(() => awaitable.GetResult());

                awaitable = Pipe.Reader.ReadAsync();
                Assert.False(awaitable.IsCompleted);
            });

            cts.Cancel();
            Assert.True(onCompletedCalled);
        }
        public void ReadAsyncNotCompletedAfterCancellation()
        {
            var onCompletedCalled = false;
            PipeAwaiter <ReadResult> awaitable = Pipe.Reader.ReadAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.True(awaitable.IsCompleted);

                ReadResult readResult = awaitable.GetResult();
                Assert.True(readResult.IsCanceled);

                awaitable = Pipe.Reader.ReadAsync();
                Assert.False(awaitable.IsCompleted);
            });

            Pipe.Reader.CancelPendingRead();
            Assert.True(onCompletedCalled);
        }
        public void OnReaderCompletedRanBeforeFlushContinuation()
        {
            var callbackRan     = false;
            var continuationRan = false;
            var pipe            = new Pipe(new PipeOptions(_pool, pauseWriterThreshold: 5));

            pipe.Writer.OnReaderCompleted(
                (exception, state) => {
                Assert.False(continuationRan);
                callbackRan = true;
            }, null);

            PipeWriter buffer = pipe.Writer.WriteEmpty(10);
            PipeAwaiter <FlushResult> awaiter = buffer.FlushAsync();

            Assert.False(awaiter.IsCompleted);
            awaiter.OnCompleted(() => { continuationRan = true; });
            pipe.Reader.Complete();

            Assert.True(callbackRan);
            pipe.Writer.Complete();
        }
Example #11
0
        public void FlushAsyncNotCompletedAfterCancellationTokenCancelled()
        {
            var        onCompletedCalled = false;
            var        cts            = new CancellationTokenSource();
            PipeWriter writableBuffer = Pipe.Writer.WriteEmpty(MaximumSizeHigh);

            PipeAwaiter <FlushResult> awaitable = writableBuffer.FlushAsync(cts.Token);

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.True(awaitable.IsCompleted);

                Assert.Throws <OperationCanceledException>(() => awaitable.GetResult());

                awaitable = writableBuffer.FlushAsync();
                Assert.False(awaitable.IsCompleted);
            });

            cts.Cancel();
            Assert.True(onCompletedCalled);
        }
Example #12
0
        public void FlushAsyncNotCompletedAfterCancellation()
        {
            var        onCompletedCalled = false;
            PipeWriter writableBuffer    = Pipe.Writer.WriteEmpty(MaximumSizeHigh);

            PipeAwaiter <FlushResult> awaitable = writableBuffer.FlushAsync();

            Assert.False(awaitable.IsCompleted);
            awaitable.OnCompleted(
                () => {
                onCompletedCalled = true;
                Assert.True(awaitable.IsCompleted);

                FlushResult flushResult = awaitable.GetResult();

                Assert.True(flushResult.IsCanceled);

                awaitable = writableBuffer.FlushAsync();
                Assert.False(awaitable.IsCompleted);
            });

            Pipe.Writer.CancelPendingFlush();
            Assert.True(onCompletedCalled);
        }