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

http: use listenerCount when adding noop event #46769

Merged
merged 5 commits into from
Mar 8, 2023

Conversation

ShogunPanda
Copy link
Contributor

Fixes #43548.
See discussion in #46523.

@nodejs-github-bot
Copy link
Collaborator

Review requested:

  • @nodejs/http
  • @nodejs/net

@ShogunPanda ShogunPanda added the request-ci Add this label to start a Jenkins CI on a PR. label Feb 22, 2023
@nodejs-github-bot nodejs-github-bot added http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run. labels Feb 22, 2023
Copy link
Member

@lpinca lpinca left a comment

Choose a reason for hiding this comment

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

See discussion in #46523 (comment)

@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Feb 22, 2023
@ShogunPanda
Copy link
Contributor Author

@lpinca

I see your point about not being a bug in Node.js. I still think we should prevent the fix anyway. So, can please others gave a final vote on this?

Other than that: do you have anything else you want me to change in this PR that I've lost in the discussion in the other issue?

@nodejs-github-bot
Copy link
Collaborator

@lpinca
Copy link
Member

lpinca commented Feb 22, 2023

I still think we should prevent the fix anyway.

The fix here actually hides the user error of keeping the socket open. If others think this is a good idea then I will dismiss my request for changes.

The events leak warning might be unhelpful but at least it tells the user that there is something wrong.

Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@ShogunPanda
Copy link
Contributor Author

@nodejs/http Can somebody else upvote or downvote this so we can reach an agreement?

@mcollina
Copy link
Member

There is a lot of legacy code out there that emits 'error' on streams manually. I think this is needed.

@lpinca
Copy link
Member

lpinca commented Feb 23, 2023

There is a lot of legacy code out there that emits 'error' on streams manually. I think this is needed.

I disagree. Note that there is no crash, only a warning and this silences it. Instead of informing the user that there is something wrong in their code, this just ignores it. In my opinion it is not an improvement, it only promotes invalid usage. Just look at the second test added here.

@mcollina
Copy link
Member

The problem is that the user must learn how to fix it. Most of those behaviors are codified in old libraries that are deep in the dependency chain, and it's close to impossible for most users to understand what's going on. My 2 cents is that we must convince them to switch from Node v0.8-era dependencies, as I don't expect those modules to be fixed.

If we want to emit a warning for this case, it should be actionable, e.g. "an error event has already been emitted on the request. Please use the destroy method instead".

@lpinca
Copy link
Member

lpinca commented Feb 23, 2023

If we want to emit a warning for this case, it should be actionable, e.g. "an error event has already been emitted on the request. Please use the destroy method instead".

Yes that would be perfect. Currently, a bad warning is better than no warning.

@ShogunPanda
Copy link
Contributor Author

So I leave the "memory leak" prevention and I add an additional warning so the user is beware of the problematic handling.
Are we good on this?

@mcollina
Copy link
Member

Yes, exactly!

@lpinca
Copy link
Member

lpinca commented Feb 23, 2023

I have no objection with that. Note that there might be other cases where the 'error' event can be emitted multiple times. I think this new warning should only handle the case where the 'clientError' event is used incorrectly.

@ShogunPanda
Copy link
Contributor Author

@mcollina @lpinca What about now? Are we good to go?

@ShogunPanda ShogunPanda added the request-ci Add this label to start a Jenkins CI on a PR. label Feb 23, 2023
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Feb 23, 2023
@nodejs-github-bot
Copy link
Collaborator

@dougwilson
Copy link
Member

I have a question. The only code needed to make the original warning appear is the following:

const fs = require('fs');
const http = require('http');

const app = (req, res) => {
  res.end(JSON.stringify({
    message: 'Hello World!'
  }));
};

const httpServer = http.createServer(app);

httpServer.listen(80, () => {
    console.log('HTTP Server running on port 80');
});

Refer to original #43548 for full reproduction steps.

Does this mean that in order to make a basic Node.js http server will also require added a clientError listener to close the socket?

@lpinca
Copy link
Member

lpinca commented Feb 23, 2023

@dougwilson

Are you able to reproduce the issue with that test case?

Does this mean that in order to make a basic Node.js http server will also require added a clientError listener to close the socket?

No, because that is what Node.js does by default if the user does not add a listener for the 'clientError' event.

@dougwilson
Copy link
Member

dougwilson commented Feb 23, 2023

Are you able to reproduce the issue with that test case?

Yes... I am using Jmeter from another machine. I will try it here on some various Node.js versions in a moment.

No, because that is what Node.js does by default if the user does not add a listener for the 'clientError' event.

Ok, then I am confused here. This PR says it is suppsoed to fix #43548 but that issue is pretty basic and doesnt add clientError listener. Is this PR to fix a different issue? I am only trying to follow the fix for #43548 so if this is not for that, please forgive me for injecting.

@lpinca
Copy link
Member

lpinca commented Feb 23, 2023

I think the whole discussion originates from #43587 where a test case was added in the form of an invalid 'clientError' listener. If the issue can be reproduced with the code in #46769 (comment), then it is a different story and my objections here fall.

@dougwilson
Copy link
Member

I am trying to whittle down a simple ideally self-contained example to reproduce the conditions Jmeter is making with the load test.

So far I at least seem to have a small example that shows what the noop listener is for, at least, if that helps in any way. Removing it causes this test to crash with unhandled exception from the server. The change in this PR doesn't break this test, which is good. It may be useful to add this to the Node.js test suite too, if it is not expected for users to add an error event handler to a basic server (not sure if that is a correct assumption -- but it seems that is what the purpose of the noop adding is). I tried this PR and it works just fine here too because it adds the noop, and for this test case socketOnError is only called the one time for the socket.

const http = require('http')

const server = http.createServer((req, res) => {
  res.end(JSON.stringify({ hello: 'world' }))
})

server.listen(3000, '127.0.0.1')

const net = require('net')

server.on('listening', () => {
  const socket = net.connect(3000, '127.0.0.1')
  socket.on('connect', () => {
    socket.write('POST /s HTTP/1.1\r\nHost: localhost\r\nTransfer-Encoding: chunked\r\n\r\n')
    socket.resume()
    setTimeout(() => {
      socket.end('z')
    }, 1000)
  })
  socket.on('close', () => server.close())
})

@lpinca
Copy link
Member

lpinca commented Feb 23, 2023

@dougwilson yes but that example does not cause the "leak" warning, does it?

@dougwilson
Copy link
Member

@dougwilson yes but that example does not cause the "leak" warning, does it?

No. I am trying to whittle down a simple ideally self-contained example to reproduce the conditions Jmeter is making with the load test.

@ShogunPanda
Copy link
Contributor Author

@lpinca I think the issue @dougwilson can eventually be handle as separate issue. Do you still want changes on this or are we good to go?

@lpinca
Copy link
Member

lpinca commented Feb 27, 2023

Yes, let's wait a little more for @dougwilson's feedback.

@ShogunPanda
Copy link
Contributor Author

@lpinca No more input received. Shall we wait more or can we land this?

@lpinca
Copy link
Member

lpinca commented Mar 2, 2023

Wait a few more days, maybe @dougwilson is busy. It is not something that needs an immediate fix and I would prefer not to revert it again.

@ShogunPanda ShogunPanda added commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. request-ci Add this label to start a Jenkins CI on a PR. labels Mar 5, 2023
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Mar 5, 2023
@nodejs-github-bot
Copy link
Collaborator

lib/_http_server.js Outdated Show resolved Hide resolved
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

@ShogunPanda ShogunPanda added the request-ci Add this label to start a Jenkins CI on a PR. label Mar 7, 2023
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Mar 7, 2023
@nodejs-github-bot
Copy link
Collaborator

@ShogunPanda ShogunPanda added the commit-queue Add this label to land a pull request using GitHub Actions. label Mar 8, 2023
@nodejs-github-bot nodejs-github-bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Mar 8, 2023
@nodejs-github-bot nodejs-github-bot merged commit 0d3faae into nodejs:main Mar 8, 2023
@nodejs-github-bot
Copy link
Collaborator

Landed in 0d3faae

@ShogunPanda ShogunPanda deleted the noop-with-haslistener branch March 8, 2023 07:53
targos pushed a commit that referenced this pull request Mar 13, 2023
PR-URL: #46769
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
targos pushed a commit that referenced this pull request Mar 14, 2023
PR-URL: #46769
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
danielleadams pushed a commit that referenced this pull request Apr 11, 2023
PR-URL: #46769
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
commit-queue-squash Add this label to instruct the Commit Queue to squash all the PR commits into the first one. http Issues or PRs related to the http subsystem. needs-ci PRs that need a full CI run.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Flooding requests results in memory leak
6 participants