Backed out 3 changesets (bug 469228) for being a possible cause of frequent test_animSVGImage.html failures a=backout

Backed out changeset 1431c80b02ef (bug 469228)
Backed out changeset 8d46046a7367 (bug 469228)
Backed out changeset 2e22c0308a7e (bug 469228)

MozReview-Commit-ID: AMRASDPCWu3

--HG--
extra : rebase_source : 46b5ee0f67ffeaec31e1ef379a2e86c20cdee989
This commit is contained in:
Wes Kocher 2017-05-10 10:13:54 -07:00
Родитель e6109d70d8
Коммит 0070a44b21
17 изменённых файлов: 31 добавлений и 333 удалений

Просмотреть файл

@ -45,7 +45,7 @@ add_task(function* () {
is(entry.request.headers.length, 9, "Check number of request headers");
is(entry.response.status, 200, "Check response status");
is(entry.response.statusText, "OK", "Check response status text");
is(entry.response.headers.length, 7, "Check number of response headers");
is(entry.response.headers.length, 6, "Check number of response headers");
is(entry.response.content.mimeType, // eslint-disable-line
"text/html", "Check response content type"); // eslint-disable-line
isnot(entry.response.content.text, undefined, // eslint-disable-line

Просмотреть файл

@ -57,8 +57,7 @@ add_task(function* () {
"last-modified: Sun, 3 May 2015 11:11:11 GMT",
"content-type: text/html",
"content-length: 465",
"connection: keep-alive",
"keep-alive: timeout=120",
"connection: close",
"server: httpd.js",
"date: Sun, 3 May 2015 11:11:11 GMT"
].join("\n");

Просмотреть файл

@ -158,9 +158,9 @@ function test() {
ok(requestItem.responseHeaders,
"There should be a responseHeaders data available.");
is(requestItem.responseHeaders.headers.length, 11,
is(requestItem.responseHeaders.headers.length, 10,
"The responseHeaders data has an incorrect |headers| property.");
is(requestItem.responseHeaders.headersSize, 360,
is(requestItem.responseHeaders.headersSize, 330,
"The responseHeaders data has an incorrect |headersSize| property.");
verifyRequestItemTarget(
@ -211,7 +211,7 @@ function test() {
"The status data has an incorrect value.");
is(requestItem.statusText, "Och Aye",
"The statusText data has an incorrect value.");
is(requestItem.headersSize, 360,
is(requestItem.headersSize, 330,
"The headersSize data has an incorrect value.");
verifyRequestItemTarget(

Просмотреть файл

@ -27,8 +27,6 @@ function handleRequest(request, response)
while ((bodyAvail = bodyStream.available()) > 0)
body += String.fromCharCode.apply(null, bodyStream.readByteArray(bodyAvail));
response.closeConnection();
if (command == "open") {
response.processAsync();
setReq(response);

Просмотреть файл

@ -161,9 +161,6 @@ const HEADERS_SUFFIX = HIDDEN_CHAR + "headers" + HIDDEN_CHAR;
/** Type used to denote SJS scripts for CGI-like functionality. */
const SJS_TYPE = "sjs";
/** The number of seconds to keep idle persistent connections alive. */
const DEFAULT_KEEP_ALIVE_TIMEOUT = 2 * 60;
/** Base for relative timestamps produced by dumpn(). */
var firstStamp = 0;
@ -241,8 +238,6 @@ const WritablePropertyBag = CC("@mozilla.org/hash-property-bag;1",
const SupportsString = CC("@mozilla.org/supports-string;1",
"nsISupportsString");
const Timer = CC("@mozilla.org/timer;1", "nsITimer");
/* These two are non-const only so a test can overwrite them. */
var BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream",
@ -396,13 +391,6 @@ function nsHttpServer()
* creation.
*/
this._connections = {};
/**
* Flag for keep-alive behavior, true for default behavior, false for
* closing connections after the first response.
* Set by nsIHttpServer.keepAlive attribute.
*/
this._keepAliveEnabled = true;
}
nsHttpServer.prototype =
{
@ -447,7 +435,14 @@ nsHttpServer.prototype =
{
var conn = new Connection(input, output, this, socket.port, trans.port,
connectionNumber);
conn.read();
var reader = new RequestReader(conn);
// XXX add request timeout functionality here!
// Note: must use main thread here, or we might get a GC that will cause
// threadsafety assertions. We really need to fix XPConnect so that
// you can actually do things in multi-threaded JS. :-(
input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
}
catch (e)
{
@ -477,7 +472,7 @@ nsHttpServer.prototype =
{
dumpn(">>> shutting down server on port " + socket.port);
for (var n in this._connections) {
if (!this._connections[n]._requestStarted || this._connections[n].isIdle()) {
if (!this._connections[n]._requestStarted) {
this._connections[n].close();
}
}
@ -748,18 +743,6 @@ nsHttpServer.prototype =
return this;
},
//
// see nsIHttpServer.keepAliveEnabled
//
get keepAliveEnabled()
{
return this._keepAliveEnabled;
},
set keepAliveEnabled(doKeepAlive)
{
this._keepAliveEnabled = doKeepAlive;
},
// NSISUPPORTS
@ -858,22 +841,6 @@ nsHttpServer.prototype =
Components.utils.forceGC();
},
/**
* Inform the server that the connection is currently in an idle state and
* may be closed when the server goes down.
*/
_connectionIdle: function(connection)
{
// If the server is down, close any now-idle connections.
if (this._socketClosed)
{
connection.close();
return;
}
connection.persist();
},
/**
* Requests that the server be shut down when possible.
*/
@ -1220,63 +1187,10 @@ function Connection(input, output, server, port, outgoingPort, number)
this._processed = false;
/** whether or not 1st line of request has been received */
this._requestStarted = false;
/**
* RequestReader may cache the port number here. This is needed because when
* going through ssltunnel, we update the Request-URL only for the first
* request, though we get knowledge of the actual target server port number.
* Subsequent requests are not updated that way and are missing the port number
* that may lead to mismatch of the target virtual server identity.
*
* Default to standard HTTP port 80 to accept common hosts (the port number is
* not sent by clients when it is the default port number for a scheme, nor
* the scheme is sent by default).
*
* See also RequestReader._validateRequest method.
*/
this._currentIncomingPort = 80;
/**
* The current keep-alive timeout duration, in seconds.
* Individual requests/responses can modify this value through the Keep-Alive header.
*/
this._keepAliveTimeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
/**
* Start the initial timeout. If no data is read from this connection within
* the keep alive timeout, then close this connection.
*/
this.persist();
this._requestStarted = false;
}
Connection.prototype =
{
/**
* Wait for an incoming data on the connection and
* expect to get a new full request.
*/
read: function()
{
dumpn("*** read on connection " + this);
this._processed = false;
this.request = null;
this.server._connectionIdle(this);
var reader = new RequestReader(this);
// XXX add request timeout functionality here!
try
{
this.input.asyncWait(reader, 0, 0, gThreadManager.mainThread);
}
catch (e)
{
this.close();
}
},
/** Closes this connection's input/output streams. */
close: function()
{
@ -1286,12 +1200,6 @@ Connection.prototype =
dumpn("*** closing connection " + this.number +
" on port " + this._outgoingPort);
if (this._idleTimer)
{
this._idleTimer.cancel();
this._idleTimer = null;
}
this.input.close();
this.output.close();
this._closed = true;
@ -1304,39 +1212,9 @@ Connection.prototype =
server.stop(function() { /* not like we can do anything better */ });
},
/** Let the connection be persistent for the keep-alive time */
persist: function()
{
// This method is called every time the connection gets to an idle state,
// i.e. has sent all queued responses out and doesn't process a request now.
var idleTimer = this._idleTimer;
if (idleTimer)
this._idleTimer.cancel();
else
this._idleTimer = idleTimer = new Timer();
dumpn("*** persisting idle connection " + this +
" for " + this._keepAliveTimeout + " seconds");
var connection = this;
idleTimer.initWithCallback(function()
{
// We might get to an active state before the timeout occurred, then
// ignore it. The timer will be rescheduled when the connection returns
// to the idle state. This is simpler and less error-prone then canceling
// the timer whenever the connection becomes active again.
if (!connection.isIdle())
return;
dumpn("*** closing idle connection " + connection);
connection.close();
}, this._keepAliveTimeout * 1000, Ci.nsITimer.TYPE_ONE_SHOT);
},
/**
* Initiates processing of this connection, using the data in the given
* request. Called by RequestReader._handleResponse after the request has
* been completely read from the socket.
* request.
*
* @param request : Request
* the request which should be processed
@ -1370,16 +1248,6 @@ Connection.prototype =
this.server._handler.handleError(code, this);
},
/**
* Returns true iff this connection is not closed and is idle.
* A connection is idle when all requests received on it have triggered responses,
* and those responses have been completely sent.
*/
isIdle: function()
{
return this.request === null && !this._closed;
},
/** Converts this to a string for debugging purposes. */
toString: function()
{
@ -1495,7 +1363,7 @@ RequestReader.prototype =
}
catch (e)
{
if (streamClosed(e) && !this._connection._closed)
if (streamClosed(e))
{
dumpn("*** WARNING: unexpected error when reading from socket; will " +
"be treated as if the input stream had been closed");
@ -1733,10 +1601,7 @@ RequestReader.prototype =
// the HTTPS case requires a tunnel/proxy and thus requires that the
// requested URI be absolute (and thus contain the necessary
// information), let's assume HTTP will prevail and use that.
// _connection._currentIncomingPort defaults to 80 (HTTP) but can be
// overwritten by the first tunneled request with a full specified URL.
// See also RequestReader.prototype._parseRequestLine.
port = +port || this._connection._currentIncomingPort;
port = +port || 80;
var scheme = identity.getScheme(host, port);
if (!scheme)
@ -1923,10 +1788,6 @@ RequestReader.prototype =
dumpn("*** serverIdentity unknown or path does not start with '/'");
throw HTTP_400;
}
// Remember the port number we have determined. Subsequent requests
// might not contain this information.
this._connection._currentIncomingPort = port;
}
var splitter = fullPath.indexOf("?");
@ -3677,17 +3538,6 @@ function Response(connection)
/** The connection over which this response will be written. */
this._connection = connection;
/**
* If true, close the connection at after the response has been sent out.
* Can be set to true whenever before end() method has been called.
* If no connection header was present then default to "keep-alive" for
* HTTP/1.1 and "close" for HTTP/1.0.
*/
var req = connection.request;
this._closeConnection = !connection.server._keepAliveEnabled ||
(req.hasHeader("Connection")
? req.getHeader("Connection").split(",").includes("close")
: !req._httpVersion.atLeast(nsHttpVersion.HTTP_1_1));
/**
* The HTTP version of this response; defaults to 1.1 if not set by the
* handler.
@ -3748,12 +3598,6 @@ function Response(connection)
*/
this._processAsync = false;
/**
* Flag indicating use of the chunked encoding to send the asynchronously
* generated content.
*/
this._chunked = false;
/**
* True iff finish() has been called on this, signaling that no more changes
* to this may be made.
@ -3935,7 +3779,6 @@ Response.prototype =
}
this._powerSeized = true;
this._closeConnection = true;
if (this._bodyOutputStream)
this._startAsyncProcessor();
},
@ -3952,25 +3795,11 @@ Response.prototype =
dumpn("*** finishing connection " + this._connection.number);
this._startAsyncProcessor(); // in case bodyOutputStream was never accessed
// If we are using chunked encoding then ensure body streams are present
// so that WriteTrhoughCopier will send an EOF chunk through.
if (this._chunked)
this.bodyOutputStream;
if (this._bodyOutputStream)
this._bodyOutputStream.close();
this._finished = true;
},
//
// see nsIHttpResponse.closeConnection
//
closeConnection: function()
{
dumpn("*** disable keep-alive for connection " + this._connection.number);
this._closeConnection = true;
},
// NSISUPPORTS
@ -4097,9 +3926,6 @@ Response.prototype =
{
dumpn("*** abort(<" + e + ">)");
// Close the connection in case of any error.
this._closeConnection = true;
// This response will be ended by the processor if one was created.
var copier = this._asyncCopier;
if (copier)
@ -4139,11 +3965,7 @@ Response.prototype =
{
NS_ASSERT(!this._ended, "ending this response twice?!?!");
if (this._closeConnection)
this._connection.close();
else
this._connection.read(); /* restart reading this keep-alive connection */
this._connection.close();
if (this._bodyOutputStream)
this._bodyOutputStream.close();
@ -4206,43 +4028,7 @@ Response.prototype =
// header post-processing
var headers = this._headers;
if (headers.hasHeader("Connection"))
{
// If "Connection: close" header had been manually set on the response,
// then set our _closeConnection flag, otherwise leave it as is.
this._closeConnection = this._closeConnection ||
headers.getHeader("Connection").split(",").includes("close");
}
else
{
// There is no Connection header set on the response, set it by state
// of the _closeConnection flag.
var connectionHeaderValue = this._closeConnection
? "close"
: "keep-alive";
headers.setHeader("Connection", connectionHeaderValue, false);
}
if (headers.hasHeader("Keep-Alive"))
{
// Read the Keep-alive header and set the timeout according it.
// Note: This is documented in RFC 2068, section 19.7.1.
var keepAliveTimeout = headers.getHeader("Keep-Alive")
.match(/^timeout=(\d+)$/);
if (keepAliveTimeout)
{
var seconds = parseInt(keepAliveTimeout[1], 10);
this._connection._keepAliveTimeout = Math.min(seconds, DEFAULT_KEEP_ALIVE_TIMEOUT);
}
}
else if (!this._closeConnection)
{
// Add the keep alive header.
headers.setHeader("Keep-Alive",
"timeout=" + this._connection._keepAliveTimeout,
false);
}
headers.setHeader("Connection", "close", false);
headers.setHeader("Server", "httpd.js", false);
if (!headers.hasHeader("Date"))
headers.setHeader("Date", toDateString(Date.now()), false);
@ -4264,11 +4050,6 @@ Response.prototype =
headers.setHeader("Content-Length", "" + avail, false);
}
this._chunked = !this._headers.hasHeader("Content-Length");
dumpn("*** this._chunked= " + this._chunked);
if (this._chunked)
headers.setHeader("Transfer-Encoding", "chunked", false);
// construct and send response
dumpn("*** header post-processing completed, sending response head...");
@ -4334,7 +4115,7 @@ Response.prototype =
var headerCopier = this._asyncCopier =
new WriteThroughCopier(responseHeadPipe.inputStream,
this._connection.output,
copyObserver, null, false);
copyObserver, null);
responseHeadPipe.outputStream.close();
@ -4397,7 +4178,7 @@ Response.prototype =
dumpn("*** starting async copier of body data...");
this._asyncCopier =
new WriteThroughCopier(this._bodyInputStream, this._connection.output,
copyObserver, null, this._chunked);
copyObserver, null);
},
/** Ensures that this hasn't been ended. */
@ -4445,12 +4226,10 @@ function wouldBlock(e)
* an observer which will be notified when the copy starts and finishes
* @param context : nsISupports
* context passed to observer when notified of start/stop
* @param chunked : boolean
* indicate whether to use chunked encoding
* @throws NS_ERROR_NULL_POINTER
* if source, sink, or observer are null
*/
function WriteThroughCopier(source, sink, observer, context, chunked)
function WriteThroughCopier(source, sink, observer, context)
{
if (!source || !sink || !observer)
throw Cr.NS_ERROR_NULL_POINTER;
@ -4467,9 +4246,6 @@ function WriteThroughCopier(source, sink, observer, context, chunked)
/** Context for the observer watching this. */
this._context = context;
/** Forces use of chunked encoding on the data */
this._chunked = chunked;
/**
* True iff this is currently being canceled (cancel has been called, the
* callback may not yet have been made).
@ -4578,37 +4354,7 @@ WriteThroughCopier.prototype =
{
var data = input.readByteArray(bytesWanted);
bytesConsumed = data.length;
var dataStr = String.fromCharCode.apply(String, data);
if (this._chunked)
{
// from RFC2616 section 3.6.1, the chunked transfer coding is defined as:
//
// Chunked-Body = *chunk
// last-chunk
// trailer
// CRLF
// chunk = chunk-size [ chunk-extension ] CRLF
// chunk-data CRLF
// chunk-size = 1*HEX
// last-chunk = 1*("0") [ chunk-extension ] CRLF
//
// chunk-extension = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
// chunk-ext-name = token
// chunk-ext-val = token | quoted-string
// chunk-data = chunk-size(OCTET)
// trailer = *(entity-header CRLF)
//
// Apply chunked encoding here
data = bytesConsumed.toString(16).toUpperCase()
+ "\r\n"
+ dataStr
+ "\r\n";
this._pendingData.push(data);
}
else
{
this._pendingData.push(dataStr);
}
this._pendingData.push(String.fromCharCode.apply(String, data));
}
dumpn("*** " + bytesConsumed + " bytes read");
@ -4876,25 +4622,6 @@ WriteThroughCopier.prototype =
dumpn("*** _doneReadingSource(0x" + e.toString(16) + ")");
this._finishSource(e);
if (this._chunked && this._sink !== null)
{
// Write the final EOF chunk
dumpn("*** _doneReadingSource - write EOF chunk");
this._chunked = false;
this._pendingData.push("0\r\n\r\n");
try
{
this._waitToWriteData();
return;
}
catch (e)
{
dumpn("!!! unexpected error waiting to write pending data: " + e);
throw e;
}
}
if (this._pendingData.length === 0)
this._sink = null;
else

Просмотреть файл

@ -19,7 +19,7 @@ interface nsIHttpServerIdentity;
/**
* An interface which represents an HTTP server.
*/
[scriptable, uuid(07a990e9-8c49-4fe5-b794-c2dc9654c0df)]
[scriptable, uuid(cea8812e-faa6-4013-9396-f9936cbb74ec)]
interface nsIHttpServer : nsISupports
{
/**
@ -218,16 +218,6 @@ interface nsIHttpServer : nsISupports
* saved state. The value may be null.
*/
void setObjectState(in AString key, in nsISupports value);
/**
* Configures use of keep-alive connections, wherein the same network
* connection may be used to receive and respond to multiple requests.
* If true, keep-alive connections will be used when possible. If false,
* keep-alive connections will not be used, and responses will include a
* "Connection: close" header.
* Defaults to true.
*/
attribute boolean keepAliveEnabled;
};
/**
@ -486,7 +476,7 @@ interface nsIHttpRequest : nsISupports
/**
* Represents an HTTP response, as described in RFC 2616, section 6.
*/
[scriptable, uuid(3116c0dc-dd5f-4864-8ebd-fd5359e0b963)]
[scriptable, uuid(1acd16c2-dc59-42fa-9160-4f26c43c1c21)]
interface nsIHttpResponse : nsISupports
{
/**
@ -627,12 +617,4 @@ interface nsIHttpResponse : nsISupports
* if processAsync() or seizePower() has not already been properly called
*/
void finish();
/**
* Signals that this response's connection will be closed after the response
* has been sent out.
* If not called, the default behavior is to reuse the connection for next
* HTTP transaction when nsIHttpServer.keepAliveEnabled is true.
*/
void closeConnection();
};

Просмотреть файл

@ -1144,7 +1144,7 @@ function CopyTest(name, next)
/** The copier used by this test. */
this._copier =
new WriteThroughCopier(this._source, this._sink, this, null, false);
new WriteThroughCopier(this._source, this._sink, this, null);
// Start watching for data written by the copier to the sink.
this._waitForWrittenData();

Просмотреть файл

@ -57,7 +57,7 @@ const HEADER_COUNT = 1000;
function commonCheck(ch)
{
do_check_true(ch.contentLength > -1);
do_check_eq(ch.getResponseHeader("connection"), "keep-alive");
do_check_eq(ch.getResponseHeader("connection"), "close");
do_check_false(ch.isNoStoreResponse());
do_check_false(ch.isPrivateResponse());
}

Просмотреть файл

@ -20,7 +20,6 @@ function run_test()
dumpn("*** run_test");
srv = createServer();
srv.keepAliveEnabled = false;
srv.registerPathHandler("/http/1.0-request", http10Request);
srv.registerPathHandler("/http/1.1-good-host", http11goodHost);

Просмотреть файл

@ -11,7 +11,6 @@
*/
var srv = createServer();
srv.keepAliveEnabled = false;
srv.start(-1);
const PORT = srv.identity.primaryPort;

Просмотреть файл

@ -383,7 +383,6 @@ function testFinished() {
function run_test() {
httpserver = new HttpServer();
httpserver.keepAliveEnabled = false;
httpserver.registerPathHandler("/test_2", handler_2);
httpserver.registerPathHandler("/test_3", handler_3);
httpserver.registerPathHandler("/test_4", handler_4);

Просмотреть файл

@ -60,7 +60,6 @@ var willRetry = 6;
function run_test() {
let ocspResponder = new HttpServer();
ocspResponder.keepAliveEnabled = false;
ocspResponder.registerPrefixHandler("/", function(request, response) {
if (gCurrentOCSPResponse) {
response.setStatusLine(request.httpVersion, 200, "OK");

Просмотреть файл

@ -255,7 +255,7 @@ add_task(async function test() {
do_check_false(content.success);
// Check some headers of the 404 response
do_check_eq(content.headers.connection, "keep-alive");
do_check_eq(content.headers.connection, "close");
do_check_eq(content.headers.server, "httpd.js");
do_check_eq(content.headers["content-length"], 14);

Просмотреть файл

@ -332,7 +332,7 @@ add_task(async function test_get_404() {
do_check_false(content.success);
// Check some headers of the 404 response
do_check_eq(content.headers.connection, "keep-alive");
do_check_eq(content.headers.connection, "close");
do_check_eq(content.headers.server, "httpd.js");
do_check_eq(content.headers["content-length"], 14);
});

Просмотреть файл

@ -650,8 +650,6 @@ Tester.prototype = {
TabDestroyObserver.wait());
barrier.wait().then(() => {
// Close all active HTTP connections.
Services.obs.notifyObservers(null, "net:prune-all-connections", null);
// Simulate memory pressure so that we're forced to free more resources
// and thus get rid of more false leaks like already terminated workers.
Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize");

Просмотреть файл

@ -666,7 +666,6 @@ var gMostRecentFirstBytePos;
add_task(function test_common_initialize() {
// Start the HTTP server.
gHttpServer = new HttpServer();
gHttpServer.keepAliveEnabled = false;
gHttpServer.registerDirectory("/", do_get_file("../data"));
gHttpServer.start(-1);
do_register_cleanup(() => {
@ -757,7 +756,7 @@ add_task(function test_common_initialize() {
gHttpServer.registerPathHandler("/shorter-than-content-length-http-1-1.txt",
function(aRequest, aResponse) {
aResponse.processAsync(false);
aResponse.processAsync();
aResponse.setStatusLine("1.1", 200, "OK");
aResponse.setHeader("Content-Type", "text/plain", false);
aResponse.setHeader("Content-Length", "" + (TEST_DATA_SHORT.length * 2),

Просмотреть файл

@ -2,5 +2,4 @@ function handleRequest(request, response) {
dump("*** Received redirect for " + request.queryString + "\n");
response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
response.setHeader("Location", request.queryString, false);
response.closeConnection();
}