Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

http response pause lets event loop exit when there's an actively ref'd connection #6305

Closed
tjfontaine opened this issue Oct 4, 2013 · 4 comments

Comments

@tjfontaine
Copy link

While there's nothing really for the child to continue doing here, so long as the connection is alive the loop should also be alive.

var common = require('../common')
var assert = require('assert');

var spawn = require('child_process').execFile;
var http = require('http');

var TOTAL_BYTES = 100 * 1024 * 1024;

if (process.argv[2] === 'child') {
  var seen = 0;

  http.get({
      hostname: '127.0.0.1',
      port: common.PORT,
      path: '/',
  }, function (res) {
      console.log('%d\ns', res.statusCode, JSON.stringify(res.headers, null, 2));

      res.on('data', function (chunk) {
        seen += chunk.length;
        console.error('chunk received: %d', chunk.length);
        res.pause();
      });

      res.once('end', function () {
        console.error('ended');
      });
  });

  process.on('exit', function() {
    // this isn't technically right, but it's more the fact that the loop is
    // exiting before it should
    console.error(seen, TOTAL_BYTES);
    assert.strictEqual(seen, TOTAL_BYTES);
  });
} else {
  var buff = new Buffer(TOTAL_BYTES);
  var server = http.createServer(function(req, res) {
    console.log('sending', buff.length);
    res.end(buff);
  }).listen(common.PORT, function() {
    var child = spawn(process.execPath,
      [process.argv[1], 'child'],
      {} //{ env: { NODE_DEBUG: 'http net' } }
    );
    child.on('close', function(code) {
      console.log('closing server');
      server.close();
      assert.strictEqual(code, 0);
    });
    child.stderr.pipe(process.stderr);
    child.stdout.pipe(process.stdout);
  });
}
@tjfontaine
Copy link
Author

Ok, so https://github.com/joyent/libuv/blob/v0.10/src/unix/stream.c#L1320-L1321 if the stream is not also writable we'll remove the stream from holding the loop open. So this seems to be the expected behavior with regard to libuv.

There's nothing left to resume the client, so the loop is reasonably free to exit the loop. It's slightly frustrating that in this case we don't notify the socket is being torn down, but doing so would potentially let the user insert more events into the event loop.

We have discussed that idea before, and there's still #5583 as an example of process.on('beforeExit') which would allow users to schedule new events to keep the loop open.

bnoordhuis added a commit to bnoordhuis/node that referenced this issue Oct 7, 2013
Unlike the 'exit' event, this event allows the user to schedule more
work and thereby postpone the exit.  That also means that the
'beforeExit' event may be emitted many times, see the attached test
case for an example.

Refs nodejs#6305.
indutny pushed a commit that referenced this issue Feb 28, 2014
Unlike the 'exit' event, this event allows the user to schedule more
work and thereby postpone the exit.  That also means that the
'beforeExit' event may be emitted many times, see the attached test
case for an example.

Refs #6305.
@jasnell
Copy link
Member

jasnell commented May 28, 2015

@indutny @bnoordhuis @tjfontaine ... any further thoughts on this one?

@bnoordhuis
Copy link
Member

I don't think this is an issue anymore but I wasn't really involved in this particular bug.

@jasnell
Copy link
Member

jasnell commented Jun 3, 2015

Closing then. Can reopen if necessary.

@jasnell jasnell closed this as completed Jun 3, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants