Skip to content

ORC Segfault when storing ref Exception from seperate thread (Nim 2.2.2) #24925

Open
@miguelmartin75

Description

@miguelmartin75

Nim Version

I tested with 2.2.4 and devel, and the following issue is patched. I am reporting to document my findings.

devel:

Nim Compiler Version 2.3.1 [Linux: amd64]
Compiled at 2025-04-30
Copyright (c) 2006-2025 by Andreas Rumpf

git hash: b5b7a127fd92349a1517d2c7e7a4f25a532fac59
active boot switches: -d:release

2.2.4:

Nim Compiler Version 2.2.4 [Linux: amd64]
Compiled at 2025-04-30
Copyright (c) 2006-2025 by Andreas Rumpf

git hash: f7145dd26efeeeb6eeae6fff649db244d81b212d
active boot switches: -d:release

For 2.2.2, the issue is present:

Nim Compiler Version 2.2.2 [Linux: amd64]
Compiled at 2025-04-11
Copyright (c) 2006-2025 by Andreas Rumpf

git hash: 6c34f62785263ad412f662f3e4e4bf8d8751d113
active boot switches: -d:release

Description

Here is a reproducible snippet, call this thread_orc_segfault.nim:

type
  MyResult = object
    value*: int
    exception*: ref Exception

proc threadFn(result: ptr MyResult) =
  proc foo(x: int): int =
    doAssert x != 42, "It can't be!"
    return x * 2

  try:
    result[].value = foo(42)
  except:
    result[].exception = getCurrentException()

let nThreads = 1

var
  outputs: seq[MyResult]
  threads: seq[Thread[ptr MyResult]]

threads.setLen(nThreads)
outputs.setLen(nThreads)

for i in 0..<nThreads:
  createThread(threads[i], threadFn, (outputs[i].addr))

for i in 0..<nThreads:
  joinThread(threads[i])

for i, o in outputs:
  if o.exception != nil:
    echo "outputs[", i, "]="
    echo o.exception.msg
    echo o.exception.getStackTrace()

Note nThreads can be set to anything >=1.

Compile and run with: nim c --mm:orc -r thread_orc_segfault.nim or nim c --mm:orc -d:useMalloc -r thread_orc_segfault.nim

Current Output

$ nim c --mm:orc -d:useMalloc -r thread_orc_segfault.nim
Hint: used config file '/home/mig/repos/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/mig/repos/Nim/config/config.nims' [Conf]
....................................................................
CC: ../Nim/lib/system/exceptions.nim
CC: ../Nim/lib/std/private/digitsutils.nim
CC: ../Nim/lib/std/assertions.nim
CC: ../Nim/lib/system/dollars.nim
CC: ../Nim/lib/std/typedthreads.nim
CC: ../Nim/lib/system.nim
CC: thread_orc_segfault.nim
Hint:  [Link]
Hint: mm: orc; threads: on; opt: none (DEBUG BUILD, `-d:release` generates faster code)
27157 lines; 0.279s; 30.926MiB peakmem; proj: /home/mig/repos/nim-issues/thread_orc_segfault.nim; out: /home/mig/repos/nim-issues/thread_orc_segfault [SuccessX]
Hint: /home/mig/repos/nim-issues/thread_orc_segfault [Exec]
outputs[0]=
/home/mig/repos/nim-issues/thread_orc_segfault.nim(8, 5) `x != 42` It can't be!
/home/mig/repos/nim-issues/thread_orc_segfault.nim(12) threadFn
/home/mig/repos/nim-issues/thread_orc_segfault.nim(8) foo
/home/mig/repos/Nim/lib/std/assertions.nim(41) failedAssertImpl
/home/mig/repos/Nim/lib/std/assertions.nim(36) raiseAssert
/home/mig/repos/Nim/lib/system/fatal.nim(53) sysFatal

Traceback (most recent call last)
/home/mig/repos/nim-issues/thread_orc_segfault.nim(19) thread_orc_segfault
/home/mig/repos/Nim/lib/system/orc.nim(521) nimDecRefIsLastCyclicDyn
/home/mig/repos/Nim/lib/system/orc.nim(503) rememberCycle
/home/mig/repos/Nim/lib/system/orc.nim(151) unregisterCycle
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Segmentation fault (core dumped)
Error: execution of an external program failed: '/home/mig/repos/nim-issues/thread_orc_segfault'

Expected Output

No segfault.

Known Workarounds

For 2.2.2:

  1. Use --mm:arc (with or without -d:useMalloc for this example), or
  2. --mm:atomicArc

Or upgrade to 2.2.4 or devel

Additional Information

No response

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