When I try to run the following example I get the error: illegal capture 'server' because ':anonymous' has the calling convention: <noconv>
How do I make this work?
import asynchttpserver, asyncdispatch
proc main() =
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
await req.respond(Http200, "Hello World")
setControlCHook(proc() {.noconv.} =
echo "Ctrl+C fired!"
server.close()
quit(1)
)
waitFor server.serve(Port(8080), cb)
main()
Result of compilation:
$ nim c -r test.nim
test.nim(10, 5) Error: illegal capture 'server' because ':anonymous' has the calling convention: <noconv>
I think you can't use closure function. Instead you should use global variables.
Thanks @xflywind for the tip.
I wrote this code to avoid several global variables. Is there a better solution?
import asynchttpserver, asyncdispatch
var stop = false
setControlCHook(proc() {.noconv.} =
stop = true
echo "Start the server shutdown ..."
)
proc shutdown(server: AsyncHttpServer) {.async.} =
while true:
if stop:
server.close()
echo "Server shutdown completed."
quit(QuitSuccess)
await sleepAsync(1000)
proc main() =
let server = newAsyncHttpServer()
# Catch ctrl-c
# asyncCheck shutdown(server, db, sessions)
asyncCheck shutdown(server)
proc cb(req: Request) {.async.} =
await req.respond(Http200, "Hello World")
waitFor server.serve(Port(8080), cb)
main()
I'm trying to compile this example. But it fails to compile. What's wrong?
import asyncdispatch
let event = newAsyncEvent()
event.addEvent(proc() = echo "test")
event.trigger()
Compiler error:
test.nim(4, 6) Error: type mismatch: got <AsyncEvent, proc (){.gcsafe, locks: 0.}>
but expected one of:
proc addEvent(ev: AsyncEvent; cb: Callback)
first type mismatch at position: 2
required type for cb: Callback
but expression 'proc () = echo ["test"]' is of type: proc (){.gcsafe, locks: 0.}
expression: addEvent(event, proc () = echo ["test"])
After doing some research I get an idea of how AsyncEvent works.
But, where to place the setControlCHook function without getting the previous error message on compilation?
import os, asyncdispatch, threadpool
proc asyncTest(): Future[string] =
let event = newAsyncEvent()
let future = newFuture[string]("asyncTest")
proc doSomeWork(event: AsyncEvent): string =
echo "Working..."
sleep(2000)
result = "Work done..."
event.trigger()
let flowVar = spawn doSomeWork(event)
proc callback(fd: AsyncFD): bool =
future.complete(^flowVar)
true
addEvent(event, callback)
return future
proc test() {.async.} =
let res = await asyncTest()
echo res
waitFor test()
echo "future return"
The best solution to gracefully terminate an asynchttpserverthat that I found!
An exception to be thrown on SIGINT.
import asynchttpserver, asyncdispatch
type EKeyboardInterrupt = object of Exception
setControlCHook(proc() {.noconv.} =
raise newException(EKeyboardInterrupt, "Keyboard Interrupt")
)
proc main() =
let server = newAsyncHttpServer()
# let dbConn = await connect2db()
proc cb(req: Request) {.async.} =
await req.respond(Http200, "Hello World")
try:
waitFor server.serve(Port(8080), cb)
except EKeyboardInterrupt:
echo "Start the server shutdown ..."
finally:
# await dbConn.close()
server.close()
echo "Server shutdown completed."
quit(QuitSuccess)
main()
This isn't cross platform, (not windows, not android), but on osx,bsd,linux there's an easy way to set up an asyncEvent to trigger on a signal. (undocumented but exported from asyncdispatch)
import asynchttpserver, asyncdispatch
import system/ansi_c #SIGINT is defined elsewhere, i.e. posix, maybe that's a better include idk i was just hoping for some sort of cross platformitude
proc main() =
let server = newAsyncHttpServer()
# let dbConn = await connect2db()
addSignal(SIGINT,proc(fd:AsyncFD):bool =
echo "Server Shutdown on SIGINT"
server.close()
quit(0)
)
proc cb(req: Request) {.async.} =
await req.respond(Http200, "Hello World")
try:
waitFor server.serve(Port(8080), cb)
except:
let e = getCurrentException
let m = if e.isNil: "None" else: e.msg
echo "Start the server shutdown ...",m
finally:
# await dbConn.close()
server.close()
echo "Server shutdown completed."
quit(QuitSuccess)
main()