Skip to content
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

OOM in test/parallel/test-stream-pipeline #353

Closed
vweevers opened this issue Aug 11, 2018 · 14 comments
Closed

OOM in test/parallel/test-stream-pipeline #353

vweevers opened this issue Aug 11, 2018 · 14 comments

Comments

@vweevers
Copy link
Contributor

On Windows 10 with node 6.8.0 x64, multiple tests in test/parallel/test-stream-pipeline.js are failing with OOM errors.

> node test\parallel\test-stream-pipeline.js
TAP version 13
ok 1 - sync run
[..]
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

I suspect the failures are related to one another, but I do not fully understand what is happening, so let's start by diving into one of them:

{
var _server = http.createServer(function (req, res) {
var rs = new Readable({
read: function () {
rs.push('hello');
},
destroy: common.mustCall(function (err, cb) {
// prevents fd leaks by destroying http pipelines
cb();
})
});
pipeline(rs, res, function () {});
});
_server.listen(0, function () {
var req = http.request({
port: _server.address().port
});
req.end();
req.on('response', function (res) {
setImmediate(function () {
res.destroy();
_server.close();
});
});
});
}

I think this test goes into an endless loop. The use of setImmediate to destroy the HTTP response, means that read on L186 will be continuously called, tick after tick. But if that's true, why doesn't it happen on other versions/platforms too?

@mcollina any idea?


Because pipeline was introduced in node 10 and the error only occurs on node 6 (I did not yet test versions between 6 and 10), I reckoned readable-stream is the proper repo for this issue - correct me if I'm wrong.

@mcollina
Copy link
Member

Can you please verify that this is the case with the latest version of Node 6 on Windows? 6.8.0 is pretty old, and it might be a Windows-specific bug.

This is either a) a Windows-bug in Node 6 (which we probably won’t fix) b) a bug in the stream machinery.

Anyway, the test should not go OOM in any case. Can you send a PR to Node core that limits the numbers of pushes to 42 (random number)? Don’t push null, as the test verifies that destroy must be called.

@vweevers
Copy link
Contributor Author

Can you please verify that this is the case with the latest version of Node 6 on Windows? 6.8.0 is pretty old, and it might be a Windows-specific bug.

Also happens on node 6.14.3.

This is either a) a Windows-bug in Node 6 (which we probably won’t fix) b) a bug in the stream machinery.

How can we find out? If we limit the number of pushes to 42, won't that hide a potential bug?

Don’t push null, as the test verifies that destroy must be called.

Roger. Side note: the lack of assertions, assertion messages or comments makes it hard to tell what the purpose of these tests is - which makes me hesitant to contribute.

@mcollina
Copy link
Member

cc @mafintosh (added the test)

IMHO that logic in that test is faulty in Node < 10, where .push call read synchronously.

@mafintosh
Copy link
Member

I'll take a look. You're probably right.

@vweevers
Copy link
Contributor Author

FWIW the OOM also happens in:

  • 9.11.2
  • 9.10.1
  • 9.7.0
  • 9.6.1
  • 9.6.0
  • 9.5.0
  • 8.11.3
  • 8.6.0
  • 6.14.3
  • 6.8.0

@vweevers
Copy link
Contributor Author

Related? This throws on node 10 (and readable-stream):

const stream = require('stream')

stream.pipeline(
  new stream.Readable({
    read (size) {
      if (this.destroyed) throw new Error('late read')
      this.push('foo')
    }
  }),
  new stream.Writable({
    write (chunk, enc, next) {
      next(new Error('stop'))
    }
  }),
  (err) => {}
)

@mcollina
Copy link
Member

@vweevers what does that throw?

@vweevers
Copy link
Contributor Author

Error: late read

@vweevers
Copy link
Contributor Author

(Intuitively, I do not expect _read to be called after destroy, but it is)

@mcollina
Copy link
Member

I think we are missing a check somewhere about this, it should not happen.

@mcollina
Copy link
Member

The following test passes:

'use strict';

const common = require('../common');
const assert = require('assert');
const { Readable } = require('stream');

const rs = new Readable({
  read: common.mustCall(function() {
    this.push('hello');
  }, 3)
});

rs.on('data', () => {
  rs.destroy();
});

It is normal that multiple _read call happens after receiving the first element. The reason for this sits in the backpressure machinery. As you can see, it happens 3 times on Node 10.

The problem you are seeing on Windows is the result of some differences in libuv between Unix and Windows, and some bad interactions between the tests: the event loop is always filled with tasks to execute and it keep accepting things. I'm sending a PR against core now to fix the test.

mcollina added a commit to mcollina/node that referenced this issue Aug 22, 2018
This test is ported automatically in readable-stream, and it fails there
on Windows and older Node.js versions because of some bad interactions
between the code and the event loop on Windows.

See: nodejs/readable-stream#353
@mcollina
Copy link
Member

@vweevers nodejs/node#22456.

mcollina added a commit to mcollina/node that referenced this issue Aug 24, 2018
This test is ported automatically in readable-stream, and it fails there
on Windows and older Node.js versions because of some bad interactions
between the code and the event loop on Windows.

See: nodejs/readable-stream#353

PR-URL: nodejs#22456
Reviewed-By: Mathias Buus <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: James M Snell <[email protected]>
targos pushed a commit to nodejs/node that referenced this issue Aug 24, 2018
This test is ported automatically in readable-stream, and it fails there
on Windows and older Node.js versions because of some bad interactions
between the code and the event loop on Windows.

See: nodejs/readable-stream#353

PR-URL: #22456
Reviewed-By: Mathias Buus <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: James M Snell <[email protected]>
targos pushed a commit to nodejs/node that referenced this issue Sep 3, 2018
This test is ported automatically in readable-stream, and it fails there
on Windows and older Node.js versions because of some bad interactions
between the code and the event loop on Windows.

See: nodejs/readable-stream#353

PR-URL: #22456
Reviewed-By: Mathias Buus <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: James M Snell <[email protected]>
@mcollina
Copy link
Member

This should be fixed in the master and 3.0.3. Please let me know!

@vweevers
Copy link
Contributor Author

@mcollina Confirmed, tests are passing on Windows. Thanks! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants