Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

Dispose of the inner HttpClient in HttpWebRequest #8470

Merged
merged 2 commits into from
May 13, 2016

Conversation

jamesqo
Copy link
Contributor

@jamesqo jamesqo commented May 12, 2016

While browsing through the code recently, I noticed that HttpWebRequest uses an HttpClient internally, which it does not dispose of afterwards. I made a quick fix to use using where the variables were initialized; since they're not saved to fields or anything I'm assuming I don't have to touch the finalizer/Dispose methods of this class. (Also assuming that since client.SendAsync is awaited immediately after it is invoked, we don't have to worry about the client being disposed before it finishes sending or anything.)

Changes:

  • Added using statements
  • Indented the code (hence why the diff is so big, try adding ?w=1 to the end of the GitHub URL to unsee whitespace changes)

cc @davidsh @stephentoub

@stephentoub
Copy link
Member

@davidsh can say for sure, but this doesn't look like a valid change to me. In particular, in some cases I'd think it must not dispose of the HttpClient as you've done, because the response stream needs to remain valid for consumption even after the async method completes.

@davidsh
Copy link
Contributor

davidsh commented May 12, 2016

In particular, in some cases I'd think it must not dispose of the HttpClient as you've done, because the response stream needs to remain valid for consumption even after the async method completes.

This is not needed. The contract design for HttpClient allows the HttpClient object to be disposed even though a particular HttpResponseMessage exists and might have data left to read from its response stream.

However, you can not dispose of the HttpResponseMessage because it will then dispose all contained objects within. And that means dispose the .Content object which contains the StreamContent of the response stream.

var request = new HttpRequestMessage(new HttpMethod(_originVerb), _requestUri);

if (_requestStream != null)
using (var handler = new HttpClientHandler())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not necessary to have a using for the handler. Disposing the HttpClient will dispose the inner handler automatically. So, it's only necessary to have the using for the HttpClient itself.

Copy link
Contributor Author

@jamesqo jamesqo May 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davidsh Fixed, thanks for pointing that out.

@stephentoub
Copy link
Member

The contract design for HttpClient allows the HttpClient object to be disposed even though a particular HttpResponseMessage exists and might have data left to read from its response stream.

In that case we're not currently handling this according to that contract on Unix. When the HttpClient is disposed, we effectively end up canceling all outstanding operations. You're saying that's not the right behavior, correct? And instead all outstanding requests/responses should be allowed to complete, with HttpClient itself preventing further requests from being started, and then all resources being cleaned up once all outstanding requests have completed?

@davidsh
Copy link
Contributor

davidsh commented May 12, 2016

You're saying that's not the right behavior, correct? And instead all outstanding requests/responses should be allowed to complete, with HttpClient itself preventing further requests from being started, and then all resources being cleaned up once all outstanding requests have completed?

Yes. It's clear from the test results that *Nix implementation is different from Windows as per this design constraint.

It's not even a design of HttpClient object itself, per se, but rather the HttpClientHandler design. The handler might be disposed (if you dispose the HttpClient, the handler gets disposed) to prevent more requests but that shouldn't close down the open network connections from the existing response streams, etc.

@davidsh
Copy link
Contributor

davidsh commented May 12, 2016

And the WinRT Windows.Web.Http.HttpClient works the same way.

@stephentoub
Copy link
Member

It's clear from the test results that *Nix implementation is different from Windows as per this design constraint.

Yes, we have explicit code in there to forcibly shut down in the case of Dispose. Having the behavior match should just entail deleting that code, something I always enjoy ;)

@davidsh
Copy link
Contributor

davidsh commented May 12, 2016

@jamesqo Thanks for working on this PR since it exposed something broken in our *Nix implementation in HttpClient.

@stephentoub We probably need more tests to validate that disposing an HttpClient won't affect reading from existing HttpResponseMessage response streams.

@stephentoub
Copy link
Member

We probably need more tests to validate that disposing an HttpClient won't affect reading from existing HttpResponseMessage response streams.

Yeah, I'll add one as part of fixing it.

@stephentoub
Copy link
Member

(It looks like Ubuntu and OSX PR legs are defined to use TestWithLocalLibraries=true, while CentOS is not. I believe that's why after my fix in #8484 the Ubuntu and OSX legs are now passing but the CentOS legs are not; those legs should start working once we update to packages that include the fix.)

@stephentoub
Copy link
Member

LGTM. Thanks, @jamesqo.

@davidsh
Copy link
Contributor

davidsh commented May 13, 2016

LGTM. We'll merge when green.

@stephentoub
Copy link
Member

Test Innerloop CentOS7.1 Debug Build and Test please
Test Innerloop CentOS7.1 Release Build and Test please

@davidsh davidsh merged commit a67304d into dotnet:master May 13, 2016
@jamesqo jamesqo deleted the webrequest-dispose branch May 13, 2016 21:45
@karelz karelz modified the milestone: 1.0.0-rtm Dec 3, 2016
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
Dispose of the inner HttpClient in HttpWebRequest

Commit migrated from dotnet/corefx@a67304d
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants