From 7cb2accb2139fd6d3e203e234ca12e1da6214e69 Mon Sep 17 00:00:00 2001 From: bung87 Date: Thu, 3 Aug 2023 18:49:33 +0800 Subject: [PATCH 1/6] add startup callback to settings --- .gitignore | 21 ++++++++++++++++++--- src/httpbeast.nim | 14 ++++++++++++++ tests/startup.ini | 7 +++++++ tests/startup.nim | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 tests/startup.ini create mode 100644 tests/startup.nim diff --git a/.gitignore b/.gitignore index f1d1222..83233aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,18 @@ -/tests/* -!/tests/*.nim -!/tests/*.cfg +* +!**/ +!*.* +*.out +.DS_Store +!.gitattributes +!.gitignore +!readme.md +!.gitkeep +!*.nim +!*.nims +!*.nimble +!*.h +!*.css +!*.html +*.exe +!*/ +nimbledeps diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 5b4c9d4..5f3bdaf 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -51,6 +51,8 @@ type OnRequest* = proc (req: Request): Future[void] {.gcsafe.} + Startup = proc () {.closure, gcsafe.} + Settings* = object port*: Port bindAddr*: string @@ -68,15 +70,23 @@ type ## 4096 for Linux/AMD64 and 128 for others. ## * listen(2) Linux manual page: https://www.man7.org/linux/man-pages/man2/listen.2.html ## * SYN packet handling int the wild: https://blog.cloudflare.com/syn-packet-handling-in-the-wild/ + startup: Startup + ## An optional callback can be provided to execute at the beginning of + ## the `eventLoop` function for initializing thread variables or performing other related tasks. HttpBeastDefect* = ref object of Defect const serverInfo = "HttpBeast" +proc doNothing(): Startup {.gcsafe.} = + result = proc () {.closure, gcsafe.} = + discard + proc initSettings*(port: Port = Port(8080), bindAddr: string = "", numThreads: int = 0, + startup: Startup = doNothing(), domain = Domain.AF_INET, reusePort = true, listenBacklog = SOMAXCONN): Settings = @@ -88,6 +98,7 @@ proc initSettings*(port: Port = Port(8080), loggers: getHandlers(), reusePort: reusePort, listenBacklog: listenBacklog, + startup: startup ) proc initData(fdKind: FdKind, ip = ""): Data = @@ -333,6 +344,9 @@ proc eventLoop( ) = let (onRequest, settings, isMainThread) = params + if settings.startup != nil: + settings.startup() + if not isMainThread: # We are on a new thread. Re-add the loggers from the main thread. for logger in settings.loggers: diff --git a/tests/startup.ini b/tests/startup.ini new file mode 100644 index 0000000..5de2e31 --- /dev/null +++ b/tests/startup.ini @@ -0,0 +1,7 @@ +charset = "utf-8" +[Package] +name = "hello" +--threads:on +[Author] +name = "nim-lang" +website = "nim-lang.org" diff --git a/tests/startup.nim b/tests/startup.nim new file mode 100644 index 0000000..83a5ba7 --- /dev/null +++ b/tests/startup.nim @@ -0,0 +1,41 @@ +import os, options, asyncdispatch, parsecfg, strutils, streams +import httpbeast + +const CurDir = currentSourcePath.parentDir + +var threadsOn {.threadvar.}: bool +var name {.threadvar.}: string + +proc onRequest(req: Request): Future[void] = + if req.httpMethod == some(HttpGet): + case req.path.get() + of "/": + req.send("name:$#,threads:$#." % [name, $threadsOn]) + else: + req.send(Http404) + +var startup = proc () = + let configFile = CurDir / "startup.ini" + var f = newFileStream(configFile, fmRead) + assert f != nil, "cannot open " & configFile + var p: CfgParser + var section: string + open(p, f, configFile) + while true: + var e = next(p) + case e.kind + of cfgEof: break + of cfgSectionStart: ## a `[section]` has been parsed + section = e.section + of cfgKeyValuePair: + if section == "Package" and e.key == "name": + name = e.value + of cfgOption: + if e.key == "threads": + if e.value == "on": + threadsOn = true + of cfgError: + echo e.msg + close(p) + +run(onRequest, initSettings(startup = startup)) From 4aa2f1a288516c7fe68448f5319f86ef24bc9929 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 7 Aug 2023 05:15:14 +0800 Subject: [PATCH 2/6] nimble -y test --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2a63eff..76397e6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,5 +26,5 @@ jobs: nimversion: ${{ matrix.nimversion }} - name: Test run: | - nimble test + nimble -y test nimble refresh From 091867a0502b1217efe35cc4e1ae82bfbbba7636 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 7 Aug 2023 06:49:14 +0800 Subject: [PATCH 3/6] cancel threads --- src/httpbeast.nim | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 5f3bdaf..0979438 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -2,6 +2,7 @@ import selectors, net, nativesockets, os, httpcore, asyncdispatch, strutils, pos import parseutils import options, sugar, logging import macros +import std/exitprocs from posix import ENOPROTOOPT @@ -558,6 +559,10 @@ proc run*(onRequest: OnRequest, settings: Settings) = createThread[(OnRequest, Settings, bool)]( t, eventLoop, (onRequest, settings, false) ) + addExitProc(proc() = + for thr in threads: + discard pthread_cancel(thr.sys) + ) else: assert false echo("Listening on port ", settings.port) # This line is used in the tester to signal readiness. From f48e0cfacc31c3a4f7e69833662476f4fcda9e56 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 7 Aug 2023 07:18:46 +0800 Subject: [PATCH 4/6] fix --- src/httpbeast.nim | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index 0979438..b25cda9 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -3,6 +3,7 @@ import parseutils import options, sugar, logging import macros import std/exitprocs +import system / ansi_c from posix import ENOPROTOOPT @@ -561,7 +562,13 @@ proc run*(onRequest: OnRequest, settings: Settings) = ) addExitProc(proc() = for thr in threads: - discard pthread_cancel(thr.sys) + when compiles(pthread_cancel(thr.sys)): + discard pthread_cancel(thr.sys) + if not isNil(thr.core): + when defined(gcDestructors): + c_free(thr.core) + else: + deallocShared(thr.core) ) else: assert false From 03e044451431d7a69fd1695ff97e52d8638696f0 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 7 Aug 2023 15:26:02 +0800 Subject: [PATCH 5/6] change addExitProc condition,thread core and sys exported from nim v2 --- src/httpbeast.nim | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index b25cda9..dbee1e6 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -560,16 +560,16 @@ proc run*(onRequest: OnRequest, settings: Settings) = createThread[(OnRequest, Settings, bool)]( t, eventLoop, (onRequest, settings, false) ) - addExitProc(proc() = - for thr in threads: - when compiles(pthread_cancel(thr.sys)): + when NimMajor >= 2: + addExitProc(proc() = + for thr in threads: discard pthread_cancel(thr.sys) - if not isNil(thr.core): - when defined(gcDestructors): - c_free(thr.core) - else: - deallocShared(thr.core) - ) + if not isNil(thr.core): + when defined(gcDestructors): + c_free(thr.core) + else: + deallocShared(thr.core) + ) else: assert false echo("Listening on port ", settings.port) # This line is used in the tester to signal readiness. From 55eb45821a4caeff27578affe034aec072052a55 Mon Sep 17 00:00:00 2001 From: bung87 Date: Mon, 7 Aug 2023 15:29:52 +0800 Subject: [PATCH 6/6] so pthread_cancel platform specific --- src/httpbeast.nim | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/httpbeast.nim b/src/httpbeast.nim index dbee1e6..af1dc26 100644 --- a/src/httpbeast.nim +++ b/src/httpbeast.nim @@ -563,7 +563,8 @@ proc run*(onRequest: OnRequest, settings: Settings) = when NimMajor >= 2: addExitProc(proc() = for thr in threads: - discard pthread_cancel(thr.sys) + when compiles(pthread_cancel(thr.sys)): + discard pthread_cancel(thr.sys) if not isNil(thr.core): when defined(gcDestructors): c_free(thr.core)