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

std(http/server): close open connections on server close #3679

Merged
merged 14 commits into from
Mar 19, 2020

Conversation

bartlomieju
Copy link
Member

@bartlomieju bartlomieju commented Jan 15, 2020

Fixes #3390

If you call server.close() on a server that has pending connections then Deno process won't exit until next request comes over for each connection.

This PR ensures that all open connections that server owns get properly closed when server is closed.

@bartlomieju bartlomieju requested a review from ry January 15, 2020 17:01
@bartlomieju bartlomieju changed the title fix: hanging HTTP server connection std(http/server): shutdown open connections on server close Jan 15, 2020
cli/ops/net.rs Outdated Show resolved Hide resolved
std/http/server.ts Show resolved Hide resolved
std/http/server.ts Show resolved Hide resolved
@bartlomieju
Copy link
Member Author

Okay after some more thought I think problem described in #3593 is caused by two separate issues:

  1. closing connection does not call shutdown on that socket causing all pending reads/writes to hang
  2. fetch now uses shared HTTP client and keeps connection open for later reuse

@bartlomieju bartlomieju force-pushed the fix_hanging_http_server branch from 57f01dd to 29e27a0 Compare January 15, 2020 19:16
std/http/server_test.ts Outdated Show resolved Hide resolved
@nayeemrmn
Copy link
Collaborator

server.close() currently makes the server stop accepting new connections without closing existing ones. This patch makes it close existing connections as well. I don't think there's any more hanging to fix in doing so and the current behaviour is probably better, right?

@bartlomieju bartlomieju force-pushed the fix_hanging_http_server branch from 29e27a0 to 9ecfbeb Compare January 15, 2020 20:01
@bartlomieju
Copy link
Member Author

server.close() currently makes the server stop accepting new connections without closing existing ones. This patch makes it close existing connections as well. I don't think there's any more hanging to fix in doing so and the current behaviour is probably better, right?

Let's see, just updated tests

@nayeemrmn
Copy link
Collaborator

@bartlomieju Okay I've seen it now (this behaviour:

If you call server.close() on a server that has pending connections then Deno process won't exit until next request comes over for each connection.

). It won't stop trying to read requests on a connection until that connection closes... which is entirely in the client's hands. This still isn't necessarily a bad thing since people can implement their own timeouts etc. -- but at the same time there will a natural expectation that the iterators break on server close. Probably the right call to drop connections then 👍.

@bartlomieju bartlomieju changed the title std(http/server): shutdown open connections on server close std(http/server): close open connections on server close Jan 15, 2020
@nayeemrmn
Copy link
Collaborator

nayeemrmn commented Jan 15, 2020

Just throwing this out there: an alternative solution would be to provide a separate server.shutdown() method to close all connections and encourage people to use it after server.close() (maybe after a timeout) when they want to clean up completely. Safe simplicity vs versatility, I'm okay with either though.

@bartlomieju
Copy link
Member Author

Just throwing this out there: an alternative solution would be to provide a separate server.shutdown() method to shutdown all connections and encourage people to use it after closing (maybe after a timeout) when they want to clean up completely. Safe simplicity vs versatility, I'm okay with either though.

Yes, we discussed that offline, and indeed server.shutdown() is desirable method that would allow to stop accepting new connections and gracefully handle already active connections.

@nayeemrmn if you'd be interested in implementing that then using Go's approach is encouraged:
https://github.com/golang/go/blob/3743d2127040c283114a247da1319c3155a81f10/src/net/http/server.go#L2648-L2691

Copy link
Collaborator

@nayeemrmn nayeemrmn left a comment

Choose a reason for hiding this comment

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

Ooh. Looks like my defs of close() and shutdown() were swapped 😅. This change is a proper starting point then.

@bartlomieju
Copy link
Member Author

Needs more investigation, closing for now

@bartlomieju bartlomieju reopened this Mar 12, 2020
@bartlomieju
Copy link
Member Author

With #4293 this PR can be moved forward

@bartlomieju bartlomieju requested a review from ry March 12, 2020 11:08
@bartlomieju
Copy link
Member Author

@ry please review

std/http/server.ts Show resolved Hide resolved
Copy link
Member

@ry ry left a comment

Choose a reason for hiding this comment

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

LGTM

@bartlomieju bartlomieju merged commit 3ef3467 into denoland:master Mar 19, 2020
@bartlomieju bartlomieju deleted the fix_hanging_http_server branch March 19, 2020 15:04
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 21, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 24, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 24, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 24, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 31, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 31, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 31, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Jan 31, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
caspervonb pushed a commit to caspervonb/deno_std that referenced this pull request Feb 1, 2021
…no#3679)

Due to structure of "Server" for each open connection there's a pending "read" op. Because connection owned by "Server" are not tracked, calling "Server.close()" doesn't close open connections.

This commit introduces simple tracking of connections for server and ensures owned connections are closed on "Server.close()".
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.

Issue with HTTP's close method
5 participants