Skip to content

threading/channels.Chan is not free of data-races according to thread-sanitizers #55

@PhilippMDoerner

Description

@PhilippMDoerner

Heyho, while working to clear up my own package of data-races I noticed that this example will declare a data-race in thread-sanitizer (tsan):

import threading/channels
type Thing = ref object

var chan = newChan[Thing]()
var thr: Thread[void]

proc loop() =
  while true:
    var msg: Thing
    let hasMsg = chan.tryRecv(msg)
    if hasMsg:
      break

proc main() =
  createThread(thr, loop)
  discard chan.trySend(Thing())

  joinThread(thr)
main()

Compiled with:
nim r --cc:clang --mm:orc -d:release -d:useMalloc -f --passc:"-fsanitize=thread -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" --debugger:native --passl:"-fsanitize=thread -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer" src/playground.nim

tsan sees a data-race here between trySend with channelSend in one thread and tryRecv with channelReceive in the other. I'm not entirely sure how to interpret that, but I would assume it is not a false positive.

Even if the data-race does not pose a real problem, I would want to solve it because users of the lib (like me) would want to tsan-check their own applications to make them as stable as can be.

I'm missing too much of an understanding of threading/channels.Chan inner working to be able to tell if that is actually the case and what these two are racing through.

Edit: Beef stated he might've seen what caused the issue. I quote: "isFull is called before a lock happens". Would changing that be the solution here? Leorize suggested to use try-acquire to get that lock or using approaches without an if there, though I can't imagine them.

tsan stacktrace ```txt WARNING: ThreadSanitizer: data race (pid=2235220) Write of size 8 at 0x7b2c00000090 by main thread (mutexes: write M0): #0 channelSend__playground_u356 /home/philipp/dev/playground/channels.nim:192:130 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed985) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1) #1 trySend__playground_u329 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:271:11 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xedf37) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1) #2 main__playground_u277 /home/philipp/dev/playground/src/playground.nim:16:27 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xedf37) #3 NimMainModule /home/philipp/dev/playground/src/playground.nim:19:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1) #4 NimMainInner /home/philipp/dev/playground/src/playground.nim:41:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320) #5 NimMain /home/philipp/dev/playground/src/playground.nim:52:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320) #6 main /home/philipp/dev/playground/src/playground.nim:60:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320)

Previous read of size 8 at 0x7b2c00000090 by thread T1:
#0 channelReceive__playground_u179 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:205:22 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed609) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#1 tryRecv__playground_u167 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:281:11 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xedcab) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#2 loop__playground_u165 /home/philipp/dev/playground/src/playground.nim:10:57 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xedcab)
#3 threadProcWrapDispatch__stdZtypedthreads_u105 /home/philipp/.choosenim/toolchains/nim-2.0.2/lib/system/threadimpl.nim:66:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed059) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#4 threadProcWrapStackFrame__stdZtypedthreads_u95 /home/philipp/.choosenim/toolchains/nim-2.0.2/lib/system/threadimpl.nim:95:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed059)
#5 threadProcWrapper__stdZtypedthreads_u81 /home/philipp/.choosenim/toolchains/nim-2.0.2/lib/system/threadimpl.nim:101:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xe7b45) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)

Location is heap block of size 176 at 0x7b2c00000000 allocated by main thread:
#0 malloc (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0x79b63) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#1 allocChannel__OOZOOZOOZOnimbleZpkgs50Zthreading4548O50O484551cd52515448515457b56abf49c5351ddfd5257ea56aef5548504856545356cZthreadingZchannels_u40 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:134:24 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed41c) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#2 newChan__playground_u4 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:316:13 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed54a) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#3 NimMainModule /home/philipp/dev/playground/src/playground.nim:4:85 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#4 NimMainInner /home/philipp/dev/playground/src/playground.nim:41:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6)
#5 NimMain /home/philipp/dev/playground/src/playground.nim:52:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6)
#6 main /home/philipp/dev/playground/src/playground.nim:60:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6)

Mutex M0 (0x7b2c00000000) created at:
#0 pthread_mutex_init (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0x99f78) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#1 initLock__coreZlocks_u7 /home/philipp/.choosenim/toolchains/nim-2.0.2/lib/core/locks.nim:38:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed45e) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#2 allocChannel__OOZOOZOOZOnimbleZpkgs50Zthreading4548O50O484551cd52515448515457b56abf49c5351ddfd5257ea56aef5548504856545356cZthreadingZchannels_u40 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:139:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed45e)
#3 newChan__playground_u4 /home/philipp/.nimble/pkgs2/threading-0.2.0-3cd4360369b8abf1c53ddfd49ea8aef70208658c/threading/channels.nim:316:13 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xed54a) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#4 NimMainModule /home/philipp/dev/playground/src/playground.nim:4:85 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#5 NimMainInner /home/philipp/dev/playground/src/playground.nim:41:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6)
#6 NimMain /home/philipp/dev/playground/src/playground.nim:52:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6)
#7 main /home/philipp/dev/playground/src/playground.nim:60:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee2f6)

Thread T1 (tid=2235222, running) created by main thread at:
#0 pthread_create (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0x64a36) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#1 createThread__stdZtypedthreads_u60 /home/philipp/.choosenim/toolchains/nim-2.0.2/lib/std/typedthreads.nim:246:103 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xe7c79) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#2 createThread__stdZtypedthreads_u51 /home/philipp/.choosenim/toolchains/nim-2.0.2/lib/std/typedthreads.nim:262:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xe7d70) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#3 main__playground_u277 /home/philipp/dev/playground/src/playground.nim:15:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xede8a) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#4 NimMainModule /home/philipp/dev/playground/src/playground.nim:19:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320) (BuildId: 92969305384c4f84ef7e6297746e94551b123ec1)
#5 NimMainInner /home/philipp/dev/playground/src/playground.nim:41:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320)
#6 NimMain /home/philipp/dev/playground/src/playground.nim:52:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320)
#7 main /home/philipp/dev/playground/src/playground.nim:60:2 (playground_1B88682F16D8AFE3768CDB5129F5ABAE744E02A7+0xee320)

SUMMARY: ThreadSanitizer: data race /home/philipp/dev/playground/channels.nim:192:130 in channelSend__playground_u356

ThreadSanitizer: reported 1 warnings

<details>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions