Skip to content

Should stopping gracefully also destroy idle sockets?#27

Open
davesteinberg wants to merge 1 commit intohunterloftis:masterfrom
davesteinberg:master
Open

Should stopping gracefully also destroy idle sockets?#27
davesteinberg wants to merge 1 commit intohunterloftis:masterfrom
davesteinberg:master

Conversation

@davesteinberg
Copy link
Copy Markdown

@davesteinberg davesteinberg commented Sep 3, 2020

I'm trying to use stoppable to shutdown a server gracefully, but I've been stymied by an extra unused connection that Chrome seems to open.

Here's a simple server that illustrates the problem (adapted from test/server.js):

const http = require('http')
const stoppable = require('..')

const grace = Number(process.argv[2] || Infinity)
const server = http.createServer((req, res) => {
  const delay = parseInt(req.url.slice(1), 10)
  res.writeHead(200)
  res.write('hello')
  setTimeout(() => res.end('world'), delay)
})
stoppable(server, grace)
server.listen(8000, () => console.log('listening'))

const stop = (code) => {
  console.log(`stopping on signal ${code}`)
  server.stop(() => console.log('stopped'))
}
process.on('SIGINT', stop)
process.on('SIGTERM', stop)

If I start the server with, say, a 5-second grace, then I get localhost:8080 in Chrome, then immediately press Ctrl-c to stop the server, I observe that it waits 5 seconds before it actually stops.

I sprinkled some console.logs through stoppable.js and discovered that Chrome (I'm using 85.0.4183.83 on macOS) is actually connecting twice, and even though stoppable is calling end() on both sockets, the close event is only firing once. After the 5 second grace timeout, it finally calls destroy(), which actually kills the second connection and allows the server to stop. I guess Chrome is being a bad citizen and ignoring the FIN sent by end()? I've tried with Firefox and httpie, and they don't have this problem (and they don't make a second connection in the first place).

What's strange is that I would expect the same problem using test/server.js, but it doesn't happen there. There are still two connections, but they both close properly. Any idea why?

In any case, my idea is that it might make sense to be more aggressive about what stoppable considers "graceful", by actually calling destroy() on idle sockets, as well. I tried making the change (this PR) and it solves my problem. All the tests still pass, too.

Any thoughts?

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

Successfully merging this pull request may close these issues.

1 participant