I'm pretty new to Nim's threading capabilities, and I'm running into what I'm sure are some basic problems. I'm working on an httpbeast based web framework, trying to call procs off object fields, and I'm getting "SIGSEGV: Illegal storage access" errors. The code runs fine with threads off, so its definitely a threading specific problem. Here is a simplified version of my code that displays the error in question:
import options, asyncdispatch
import httpbeast
type ComponentType = tuple[render: proc (): string {.closure, gcsafe.}]
var comp {.threadvar.}: ComponentType
comp = block:
proc render(): string {.closure, gcsafe.} = "hello "
(render: render)
var page {.threadvar.}: ComponentType
page = block:
proc render(): string {.closure, gcsafe.} = comp.render() & "me"
(render: render)
proc onRequest(req: Request): Future[void] =
if req.httpMethod == some(HttpGet):
case req.path.get()
of "/":
req.send(page.render()) # Segmentation fault here
else:
req.send(Http404)
run(onRequest)
My understanding is that threadvars get initialized for each thread, so I figured the component tuples would exist with their procs on each thread. This is compiled with 1.6.6 stable compiler and default gc. Interestingly enough, if I compile with gc:arc the program crashes instantly (with default it crashes when processing a request) and if I compile with gc:orc it sometimes succeeds and returns a response, but other time crashes on request.
Looking for any advice or troubleshooting help, thanks in advance.
A threadvar needs to be initialised manually per-thread. I guess your expectation is that assigning the value in one thread will assign the same one in all threads, that is not the case. You will only assign it in the main thread. Best way to do what you want is to create a proc for each threadvar and then use it on any accesses to that threadvar, for example getComp:
proc getComp(): ComponentType =
if comp.isNil:
comp = # Init comp
return comp
(Note that you need to make your ComponentType a ref in that case)