-
Couldn't load subscription status.
- Fork 561
Try to avoid ObjectDisposedException when writing output
#8632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3b895d4
b42a248
34c89a8
7bfec48
bb425e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -361,7 +361,13 @@ Task ConnectAsync (HttpURLConnection httpConnection, CancellationToken ct) | |
| protected virtual async Task WriteRequestContentToOutput (HttpRequestMessage request, HttpURLConnection httpConnection, CancellationToken cancellationToken) | ||
| { | ||
| using (var stream = await request.Content.ReadAsStreamAsync ().ConfigureAwait (false)) { | ||
| await stream.CopyToAsync(httpConnection.OutputStream!, 4096, cancellationToken).ConfigureAwait(false); | ||
| cancellationToken.ThrowIfCancellationRequested (); | ||
| try { | ||
| await stream.CopyToAsync(httpConnection.OutputStream!, 4096, cancellationToken).ConfigureAwait(false); | ||
| } catch (ObjectDisposedException ex) { | ||
| Logger.Log (LogLevel.Error, LOG_APP, $"Stream disposed while copying the content stream to output: {ex}"); | ||
| cancellationToken.ThrowIfCancellationRequested (); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels a tad odd: we're in a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine, since the method returns a |
||
| } | ||
|
|
||
| // | ||
| // Rewind the stream to beginning in case the HttpContent implementation | ||
|
|
@@ -381,8 +387,15 @@ protected virtual async Task WriteRequestContentToOutput (HttpRequestMessage req | |
| // | ||
| // See https://bugzilla.xamarin.com/show_bug.cgi?id=55477 | ||
| // | ||
| if (stream.CanSeek) | ||
| stream.Seek (0, SeekOrigin.Begin); | ||
| if (stream.CanSeek) { | ||
| cancellationToken.ThrowIfCancellationRequested (); | ||
| try { | ||
| stream.Seek (0, SeekOrigin.Begin); | ||
| } catch (ObjectDisposedException ex) { | ||
| Logger.Log (LogLevel.Error, LOG_APP, $"Stream disposed while seeking to the beginning of the content stream: {ex}"); | ||
| cancellationToken.ThrowIfCancellationRequested (); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given this observation, perhaps we should/also check
httpConnection.OutputStream.CanWrite.If
httpConnection.OutputStream.CanWriteis false -- possibly because it was disposed, possibly because The Gods Must Be Crazy -- then What Should We Do? Throw an exception? Return a failed Task?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checking
CanWriteonly tells us whether the stream is capable of writing, not whether it's able to do so. IOW, in many cases in the BCL atruereturned from the property is not influenced by the stream state:While the content streams do change the value of the property based on (portions) of their state, I don't think we should (and can) rely on that value, as per docs:
I read the "supports" as "is capable of" and not "is able to right now".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "the current stream" is the important clause. Consider code such as:
if that
stream.Write()will throw, then what's the point of thestream.CanWritecheck? (Sure, it can't check everything, e.g. the network might suddenly disappear or your disk runs out of space, sostream.Write(…)may throw. However, if you know that all writes will fail, thenstream.CanWriteshould return false!)