i'm fighting with an async in a thread example, does one have a tip where my big mistake is? It works for a few http request then crashes, it crashes faster in release, but not crashes withouth gc (or not discovered yet...)
import locks
import os
import asyncdispatch
import asynchttpserver, asyncdispatch
var L: Lock
type Context = ref object {.pure.}
num: int
str: string
proc th(ctxP: pointer) {.thread.} =
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
var idx: int = 0
if not tryAcquire(L): return
var ctx = cast[ref Context](ctxP)
GC_ref ctx # ????
ctx[].num.inc()
idx = ctx[].num
GC_unref ctx # ????
release(L)
await req.respond(Http200, "Hello World " & $idx)
proc aprint(): Future[void] {.async.} =
while true:
echo "hello"
await sleepAsync 5000
asyncCheck aprint()
asyncCheck server.serve(Port(8080), cb)
runForever()
initLock(L)
var ctx = Context(num: 0, str: "")
var ctxP = ctx.addr
GC_ref ctx # ????
var networkThread: Thread[pointer]
networkThread.createThread(th, ctxP)
while true:
if not tryAcquire(L):
echo "could not aquire lock"
sleep(50)
continue
ctx.num.inc
echo(ctx.num)
release(L)
sleep(2500)
it crashes with:
10004
10263
hello
Traceback (most recent call last)
threadAsync.nim(30) th
asyncdispatch.nim(1651) runForever
asyncdispatch.nim(1516) poll
asyncdispatch.nim(1282) runOnce
asyncdispatch.nim(191) processPendingCallbacks
asyncmacro.nim(36) serve_continue
asynchttpserver.nim(309) serveIter
asyncmacro.nim(307) processClient
asyncmacro.nim(36) processClient_continue
asynchttpserver.nim(281) processClientIter
asyncfutures.nim(77) newFutureVar
asyncfutures.nim(59) newFuture
strmantle.nim(63) nimIntToStr
gc.nim(475) newObj
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Error: execution of an external program failed: '/home/david/nimPlayground/threadAsync '
I've stressed it with:
true; do curl 127.0.0.1:8080; done
Hi, try this (works for me) and I put some comments in it:
import locks
import os
import asyncdispatch
import asynchttpserver, asyncdispatch
var L: Lock
type Context = ref object {.pure.}
num: int
str: string
proc th(ctxP: pointer) {.thread.} =
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
var idx: int = 0
if not tryAcquire(L): return
var ctx = cast[ptr Context](ctxP) # never cast ptr to ref
# within different thread
# GC_ref ctx # ???? not needed because ctx is not owned by this thread
ctx[].num.inc()
idx = ctx[].num
sleep(200) # sleep while locking to get the: "could not acquire lock" msg
# GC_unref ctx # ????
release(L)
await req.respond(Http200, "Hello World " & $idx)
proc aprint(): Future[void] {.async.} =
while true:
echo "hello"
await sleepAsync 1000
asyncCheck aprint()
asyncCheck server.serve(Port(8080), cb)
runForever()
initLock(L)
let ctx = Context(num: 0, str: "")
var ctxP = ctx.unsafeAddr
# GC_ref ctx # parentthread is owner of ctx (I think its not needed because of the
# endless loop)
var networkThread: Thread[pointer]
networkThread.createThread(th, ctxP)
while true:
if not tryAcquire(L):
echo "could not aquire lock"
sleep(50)
continue
ctx.num.inc
echo(ctx.num)
release(L)
sleep(2500)