Skip to content

Unable to access closed stream #1822

Closed

Description

@kendallb

Describe the bug
We did not have this issue with v106, but since moving to v107 we are now having issues when trying to read from the response stream into a file where we get an error saying you cannot read from a closed stream. So I suspect that somehow the response stream is being closed before we have finished reading from it? The request is set up like this:

                    var request = new RestRequest {
                        ResponseWriter = responseStream => {
                            var buffer = new byte[81920];
                            int count;
                            while ((count = responseStream.Read(buffer, 0, buffer.Length)) != 0) {
                                stream.Write(buffer, 0, count);
                            }
                            return responseStream;
                        },
                    };
                    request.Resource = resource;
                    request.Method = Method.Get;
                    return request;

Is there perhaps a different way we should be reading the response stream with v107?

Desktop (please complete the following information):

  • Windows Server 2016
  • .NET Framework
  • Version 4.8

Activity

  1. kendallb commented on Mar 30, 2022

    @kendallb
    ContributorAuthor

    I think the issue is when it gets here:

    var bytes = stream == null ? null : await stream.ReadAsBytes(cancellationToken).ConfigureAwait(false);

    as it tries to read the stream, but I have already processed it and downloaded everything from it. Maybe in HttpClient once the stream his the EOF it gets closed sometimes? The error is random. Looks like I can avert the issue by return null from the ResponseWriter callback, but I think I might just refactor the code to use DownloadStreamAsync to fix this.

  2. kendallb commented on Mar 30, 2022

    @kendallb
    ContributorAuthor

    Yep it looks like that is the case, as here is the stack trace. Got any ideas for how to fix this as it might bite other folks?

    Cannot access a closed Stream.
    
       at System.IO.__Error.StreamIsClosed()
       at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
       at System.IO.MemoryStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
       at RestSharp.Extensions.MiscExtensions.<ReadAsBytes>d__0.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
       at RestSharp.RestResponse.<>c__DisplayClass0_0.<<FromHttpResponse>g__GetDefaultResponse|0>d.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
       at RestSharp.RestResponse.<FromHttpResponse>d__0.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
       at RestSharp.RestClient.<ExecuteAsync>d__1.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at AMain.RestClientHelper.ClientHelper.<ExecuteRequest>d__16.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at AMain.RestClientHelper.ClientHelper.<Execute>d__20.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
       at AMain.Helpers.AsyncHelpers.<>c__DisplayClass1_0`1.<<RunSync>b__0>d.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
       at AMain.Helpers.AsyncHelpers.CustomSynchronizationContext.<<Run>b__7_0>d.MoveNext()
    --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
       at AMain.Helpers.AsyncHelpers.CustomSynchronizationContext.Run()
       at AMain.Helpers.AsyncHelpers.RunSync(Func`1 task)
       at AMain.Helpers.AsyncHelpers.RunSync[T](Func`1 task)
       at AMain.DataAccess.RestClients.RestClientBase.Execute(Int32 timeout, Stream stream, IDictionary`2 args, Nullable`1 maxRetries, String resource)
       at AMain.DataAccess.RestClients.ImageFilesClient.GetFile(String path, Stream stream, Boolean usePublicServer)
    
  3. alexeyzimarev commented on Mar 30, 2022

    @alexeyzimarev
    Member

    I need to check. I don't like the response writer as it's synchronous. I think there are tests for it, but I might be mistaken.

    If the response writer is set, the code you found should read from the modified stream.

  4. kendallb commented on Mar 31, 2022

    @kendallb
    ContributorAuthor

    Yeah the stream should be empty so should do nothing, but sometimes it appears the stream is closed. Almost like it gets closed as soon as we read the last byte from it.

    I have a change to test that by returning null so the attempt to read the stream is bypassed. But maybe if there is a response reader callback it should just not read from the stream at all?

    I am trying to use download stream but can’t yet as I need to see the response status so I have another ticket open for that.

  5. kendallb commented on Mar 31, 2022

    @kendallb
    ContributorAuthor

    Yes, not reading from the stream does fix it. I don't know the stream is getting closed by .net, but at the end of the day if there is a ResponseWriter callback to process the stream, it makes no sense to read what might be left in the stream into the result. You would expect whoever set up the callback wants to process the entire stream.

    So I created a PR to fix this issue and not require the user to return null from the callback to resolve this.

  6. stale commented on May 1, 2022

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

  7. repo-ranger commented on May 1, 2022

    @repo-ranger

    ⚠️ This issue has been marked wontfix and will be closed in 3 days

  8. stale commented on Jun 13, 2022

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions