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

Impossible to run Kemal with reuse_port: true #459

Closed
vlazar opened this issue Jun 23, 2018 · 7 comments
Closed

Impossible to run Kemal with reuse_port: true #459

vlazar opened this issue Jun 23, 2018 · 7 comments
Labels

Comments

@vlazar
Copy link

vlazar commented Jun 23, 2018

Description

Due to changes in HTTP::Server API in Crystal 0.25.0 and the way Kemal 0.23.0 starts server it's now impossible to run Kemal with reuse_port: true.

Ref: https://github.com/kemalcr/kemal/pull/452/files#diff-e5663d7073109a4b406e96582b8cb5c2R71

The problem is listen now also does bind_tcp:

Ref: https://github.com/crystal-lang/crystal/blob/7fb783f7afec0a199d6f22ef78aae0f45517068a/src/http/server.cr#L216-L220

Steps to Reproduce

# reuse_port_issue.cr
require "kemal"

get "/plaintext" do |env|
  env.response.content_type = "text/plain"
  "Hello, World!"
end

Kemal.config do |cfg|
  cfg.serve_static = false
  cfg.logging = false
end

Kemal.run do |cfg|
  cfg.server.not_nil!.bind_tcp(cfg.port, reuse_port: true)
end
$ crystal reuse_port_issue.cr

Expected behavior: It is possible to run Kemal with reuse_port: true

Actual behavior: Unhandled exception: bind: Address already in use (Errno)

Reproduces how often: Always

Versions

Kemal 0.23.0

$ crystal --version
Crystal 0.25.0 (2018-06-20)

LLVM: 5.0.1
Default target: x86_64-apple-macosx

Additional Information

Trying to update TFB to latest Crystal and frameworks here TechEmpower/FrameworkBenchmarks@e6c2f95#diff-7a0f270376d33ada73bacaf95cf345fbL116

TechEmpower/FrameworkBenchmarks#3884

@waghanza
Copy link
Contributor

@vlazar Same issue if port is 3000

@waghanza
Copy link
Contributor

using listen it works

@vlazar
Copy link
Author

vlazar commented Jun 28, 2018

@waghanza I'm not sure what do you mean by listen works. Can you share the code?

@waghanza
Copy link
Contributor

@vlazar sorry, I think I have to give more details

Kemal.run { |cfg| cfg.server.not_nil!.bind_tcp("0.0.0.0",3000, reuse_port: true) }

seems not to work for me, but

Kemal.run { |cfg| cfg.server.not_nil!.listen("0.0.0.0",3000, reuse_port: true) }

works

@straight-shoota
Copy link
Contributor

Yes, this works because listen blocks the current fiber and the code won't reach the second listen call until the server is stopped. It's not nice but fine as a quick workaround.

@waghanza
Copy link
Contributor

@straight-shoota thanks for explanation

@vlazar
Copy link
Author

vlazar commented Jun 28, 2018

@straight-shoota Thanks for explanation! TIL. I thought with @waghanza example two server.listen calls were actually made and created 2 sockets internally. It turns out that's not the case.

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

No branches or pull requests

4 participants