Bug 20267 - Calling HttpListenerResponse.Close() more than once causes keep-alive sockets to close
Summary: Calling HttpListenerResponse.Close() more than once causes keep-alive sockets...
Alias: None
Product: Class Libraries
Classification: Mono
Component: System.Web ()
Version: 3.4.0
Hardware: PC Linux
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2014-06-02 11:28 UTC by Craig Minihan
Modified: 2014-06-03 08:28 UTC (History)
1 user (show)

Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Craig Minihan 2014-06-02 11:28:40 UTC
If HttpListenerResponse.Close() is called more than once then the keep-alive mechanism in HttpConnection can be fooled into closing an active request socket recycled in the first Close call.

The problem is in System.Net's HttpConnection.cs Close method. This extracted block shows the issue:

if (!force_close && context.Request.FlushInput ()) {
	if (chunked && context.Response.ForceCloseChunked == false) {
		// Don't close. Keep working.
		Unbind ();
		Init ();
		BeginReadRequest ();

	Unbind ();
	Init ();
	BeginReadRequest ();

Socket s = sock;
sock = null;
try {
	if (s != null)
		s.Shutdown (SocketShutdown.Both);
} catch {
} finally {
	if (s != null)
		s.Close ();

On the first call it is likely that the first IF is entered, thereby reusing the connection. On the second call if FlushInput() returns false we end up closing the socket. It is highly likely that FlushInput() will return false if it is processing chunked request data.

A simple (dumb) replication case:

void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
    // stuff happens ...
    // more stuff happens ... time passes ...
    response.Close(); // <<<< now we are in trouble
Comment 1 Craig Minihan 2014-06-03 08:28:58 UTC
I'll raise this in another defect since I have more info on the problem which is slightly different to what I've reported here.