-
Notifications
You must be signed in to change notification settings - Fork 552
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.CanWrite
is 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
CanWrite
only tells us whether the stream is capable of writing, not whether it's able to do so. IOW, in many cases in the BCL atrue
returned 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.CanWrite
check? (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.CanWrite
should return false!)