Preserve OCE.CancellationToken in StreamPipeReader (#82745)
authorStephen Halter <halter73@gmail.com>
Tue, 28 Feb 2023 15:00:37 +0000 (07:00 -0800)
committerGitHub <noreply@github.com>
Tue, 28 Feb 2023 15:00:37 +0000 (10:00 -0500)
src/libraries/System.IO.Pipelines/src/System/IO/Pipelines/StreamPipeReader.cs
src/libraries/System.IO.Pipelines/tests/StreamPipeReaderTests.cs

index 47ccc47..05e358e 100644 (file)
@@ -262,11 +262,16 @@ namespace System.IO.Pipelines
                             reader._isStreamCompleted = true;
                         }
                     }
-                    catch (OperationCanceledException)
+                    catch (OperationCanceledException ex)
                     {
                         reader.ClearCancellationToken();
 
-                        if (tokenSource.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
+                        if (cancellationToken.IsCancellationRequested)
+                        {
+                            // Simulate an OCE triggered directly by the cancellationToken rather than the InternalTokenSource
+                            throw new OperationCanceledException(ex.Message, ex, cancellationToken);
+                        }
+                        else if (tokenSource.IsCancellationRequested)
                         {
                             // Catch cancellation and translate it into setting isCanceled = true
                             isCanceled = true;
@@ -275,7 +280,6 @@ namespace System.IO.Pipelines
                         {
                             throw;
                         }
-
                     }
 
                     return new ReadResult(reader.GetCurrentReadOnlySequence(), isCanceled, reader._isStreamCompleted);
index a59af1d..f70373c 100644 (file)
@@ -263,7 +263,9 @@ namespace System.IO.Pipelines.Tests
 
             stream.WaitForReadTask.TrySetResult(null);
 
-            await Assert.ThrowsAsync<OperationCanceledException>(async () => await task);
+            var oce = await Assert.ThrowsAsync<OperationCanceledException>(async () => await task);
+            Assert.Equal(cts.Token, oce.CancellationToken);
+            Assert.IsType<OperationCanceledException>(oce.InnerException);
             reader.Complete();
         }