From 39b93cf0b11cf9c0a4c517f10f6c7ce69ed87fd9 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Wed, 17 Apr 2019 10:09:08 -0700 Subject: [PATCH 1/7] httpbeast: option to set reusePort --- src/httpbeast.nim | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index a2524fe..71818dd 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -54,6 +54,9 @@ type domain*: Domain numThreads: int loggers: seq[Logger] + reusePort*: bool + # when false, will fail if --threads is passed or if 2 + # processes bind to same address/port HttpBeastDefect* = ref object of Defect @@ -63,14 +66,14 @@ const proc initSettings*(port: Port = Port(8080), bindAddr: string = "", numThreads: int = 0, - domain = Domain.AF_INET): Settings = - + domain = Domain.AF_INET, reusePort = true): Settings = Settings( port: port, bindAddr: bindAddr, domain: domain, numThreads: numThreads, - loggers: getHandlers() + loggers: getHandlers(), + reusePort: reusePort, ) proc initData(fdKind: FdKind, ip = ""): Data = @@ -317,7 +320,7 @@ proc eventLoop(params: (OnRequest, Settings)) = let server = newSocket(settings.domain) server.setSockOpt(OptReuseAddr, true) - server.setSockOpt(OptReusePort, true) + server.setSockOpt(OptReusePort, settings.reusePort) server.bindAddr(settings.port, settings.bindAddr) server.listen() server.getFd().setBlocking(false) From d6564d039688cfd41b39a23485f9bca935459236 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 27 Jun 2021 14:52:39 -0700 Subject: [PATCH 2/7] bump version --- httpbeast.nimble | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpbeast.nimble b/httpbeast.nimble index 7180773..ea2be4e 100644 --- a/httpbeast.nimble +++ b/httpbeast.nimble @@ -1,6 +1,6 @@ # Package -version = "0.3.0" +version = "0.4.0" author = "Dominik Picheta" description = "A super-fast epoll-backed and parallel HTTP server." license = "MIT" From 64310f42e64e067984bbe286b84267014da6d5a2 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Sun, 27 Jun 2021 15:42:52 -0700 Subject: [PATCH 3/7] fix tests (use an Option to make code backward compatible) --- src/httpbeast.nim | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 71818dd..e783cd3 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -54,9 +54,10 @@ type domain*: Domain numThreads: int loggers: seq[Logger] - reusePort*: bool + reusePort*: Option[bool] # when false, will fail if --threads is passed or if 2 - # processes bind to same address/port + # processes bind to same address/port. We use an Option to avoid + # breaking code that relies on `Settings(port: port)` HttpBeastDefect* = ref object of Defect @@ -73,7 +74,7 @@ proc initSettings*(port: Port = Port(8080), domain: domain, numThreads: numThreads, loggers: getHandlers(), - reusePort: reusePort, + reusePort: some(reusePort), ) proc initData(fdKind: FdKind, ip = ""): Data = @@ -320,7 +321,7 @@ proc eventLoop(params: (OnRequest, Settings)) = let server = newSocket(settings.domain) server.setSockOpt(OptReuseAddr, true) - server.setSockOpt(OptReusePort, settings.reusePort) + server.setSockOpt(OptReusePort, settings.reusePort.get(true)) server.bindAddr(settings.port, settings.bindAddr) server.listen() server.getFd().setBlocking(false) From e08209b9b9abc028dbc734658baea8870e75e829 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Thu, 1 Jul 2021 17:02:43 -0700 Subject: [PATCH 4/7] ignore reusePort when running with multiple threads for now --- src/httpbeast.nim | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index e783cd3..2e1edfe 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -54,10 +54,9 @@ type domain*: Domain numThreads: int loggers: seq[Logger] - reusePort*: Option[bool] - # when false, will fail if --threads is passed or if 2 - # processes bind to same address/port. We use an Option to avoid - # breaking code that relies on `Settings(port: port)` + reusePort: bool + ## controlls whether to fail with "Address already in use". + ## This is currently ignored if multiple threads are spawned. HttpBeastDefect* = ref object of Defect @@ -67,14 +66,15 @@ const proc initSettings*(port: Port = Port(8080), bindAddr: string = "", numThreads: int = 0, - domain = Domain.AF_INET, reusePort = true): Settings = + domain = Domain.AF_INET, + reusePort = false): Settings = Settings( port: port, bindAddr: bindAddr, domain: domain, numThreads: numThreads, loggers: getHandlers(), - reusePort: some(reusePort), + reusePort: reusePort, ) proc initData(fdKind: FdKind, ip = ""): Data = @@ -321,7 +321,7 @@ proc eventLoop(params: (OnRequest, Settings)) = let server = newSocket(settings.domain) server.setSockOpt(OptReuseAddr, true) - server.setSockOpt(OptReusePort, settings.reusePort.get(true)) + server.setSockOpt(OptReusePort, settings.reusePort) server.bindAddr(settings.port, settings.bindAddr) server.listen() server.getFd().setBlocking(false) @@ -477,8 +477,13 @@ proc run*(onRequest: OnRequest, settings: Settings) = when compileOption("threads"): var threads = newSeq[Thread[(OnRequest, Settings)]](numThreads) for i in 0 ..< numThreads: + var settings2 = settings + if numThreads > 1: settings2.reusePort = true + # TODO: in future work, we can honor `reusePort = false` by + # attempting to bind to the port, and then on success spawn the threads + # with `reusePort = false`. createThread[(OnRequest, Settings)]( - threads[i], eventLoop, (onRequest, settings) + threads[i], eventLoop, (onRequest, settings2) ) echo("Listening on port ", settings.port) # This line is used in the tester to signal readiness. joinThreads(threads) From c316b87e2a66bccbee38ea050a351bde848a3add Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 2 Jul 2021 21:36:33 +0100 Subject: [PATCH 5/7] Apply suggestions from code review --- src/httpbeast.nim | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 2e1edfe..04583d4 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -55,8 +55,8 @@ type numThreads: int loggers: seq[Logger] reusePort: bool - ## controlls whether to fail with "Address already in use". - ## This is currently ignored if multiple threads are spawned. + ## controls whether to fail with "Address already in use". + ## Setting this to false will raise when `threads` are on. HttpBeastDefect* = ref object of Defect @@ -321,6 +321,8 @@ proc eventLoop(params: (OnRequest, Settings)) = let server = newSocket(settings.domain) server.setSockOpt(OptReuseAddr, true) + if compileOption("threads") and not settings.reusePort: + raise newException(HttpBeastDefect, "--threads:on requires reusePort to be enabled in settings") server.setSockOpt(OptReusePort, settings.reusePort) server.bindAddr(settings.port, settings.bindAddr) server.listen() @@ -477,13 +479,8 @@ proc run*(onRequest: OnRequest, settings: Settings) = when compileOption("threads"): var threads = newSeq[Thread[(OnRequest, Settings)]](numThreads) for i in 0 ..< numThreads: - var settings2 = settings - if numThreads > 1: settings2.reusePort = true - # TODO: in future work, we can honor `reusePort = false` by - # attempting to bind to the port, and then on success spawn the threads - # with `reusePort = false`. createThread[(OnRequest, Settings)]( - threads[i], eventLoop, (onRequest, settings2) + threads[i], eventLoop, (onRequest, settings) ) echo("Listening on port ", settings.port) # This line is used in the tester to signal readiness. joinThreads(threads) From eca38f91a41261b086c329aed6a972c9993f7708 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 2 Jul 2021 21:40:22 +0100 Subject: [PATCH 6/7] Update src/httpbeast.nim --- src/httpbeast.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 04583d4..4204b19 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -322,7 +322,7 @@ proc eventLoop(params: (OnRequest, Settings)) = let server = newSocket(settings.domain) server.setSockOpt(OptReuseAddr, true) if compileOption("threads") and not settings.reusePort: - raise newException(HttpBeastDefect, "--threads:on requires reusePort to be enabled in settings") + raise HttpBeastDefect(msg: "--threads:on requires reusePort to be enabled in settings") server.setSockOpt(OptReusePort, settings.reusePort) server.bindAddr(settings.port, settings.bindAddr) server.listen() From 804d42cb519d020dacdbdd6aa778190a3b164f10 Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Fri, 2 Jul 2021 21:42:03 +0100 Subject: [PATCH 7/7] Update src/httpbeast.nim --- src/httpbeast.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 4204b19..118fa32 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -67,7 +67,7 @@ proc initSettings*(port: Port = Port(8080), bindAddr: string = "", numThreads: int = 0, domain = Domain.AF_INET, - reusePort = false): Settings = + reusePort = true): Settings = Settings( port: port, bindAddr: bindAddr,