When compiling and running the following code (testme.nim) under Ubuntu 15.10 with the latest devel branch, I get a segfault pretty fast.
import times, os
var
workerThread1: Thread[tuple[na: int]]
workerThread2: Thread[tuple[na: int]]
proc workerRun1(params: tuple[na: int]) {.thread.} =
while true:
let k = getDateStr()
echo "1: ", k
sleep(10)
proc workerRun2(params: tuple[na: int]) {.thread.} =
while true:
let k = getDateStr()
echo "2: ", k
sleep(10)
createThread(workerThread1, workerRun1, (na:0))
createThread(workerThread2, workerRun2, (na:0))
joinThread(workerThread1)
joinThread(workerThread2)
Output:
2: 2015-12-12
1: 2015-12-12
2: 2015-12-12
1: 2015-12-12
2: 2015-12-12
1: 2015-12-12
2: 2015-12-12
1: 2015-12-12
1: 2015-12-12
Traceback (most recent call last)
testme.nim(15) workerRun2
times.nim(583) getDateStr
times.nim(444) getLocalTime
times.nim(403) tmToTimeInfo
times.nim(489) getTzname
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Looking at getTzName() shows:
...
var
tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
...
proc getTzname(): tuple[nonDST, DST: string] =
return ($tzname[0], $tzname[1])
It seems the $ operator is not thread safe. Is there any workaround I can use?
I played around a bit with getTzname() and it seems that sometimes during runtime tzname[0] or tzname[1] is nil. tzname was initialized using tzset() globally, though.
var
timezone {.importc, header: "<time.h>".}: int
tzname {.importc, header: "<time.h>" .}: array[0..1, cstring]
# we also need tzset() to make sure that tzname is initialized
proc tzset() {.importc, header: "<time.h>".}
# calling tzset() implicitly to initialize tzname data.
tzset()
I filed an issue on github: https://github.com/nim-lang/Nim/issues/3642