First up, thanks a ton for making me aware of "onThreadDestruction", I was very much not aware and am a huge fan of more explicit hooks like that. I'll include that going forward for sure.
Next up, regarding the ThreadDispatcher: > Looking at the log you provided in the GitHub issue, the internal per-thread dispatcher (which is a ref object) is what causes the leak, as .threadvar's aren't destroyed on thread exit. The problem here is that I seemingly can't clean this up properly. Trying to nil it will... okay I just tried that attempt out again for like the 5th time or so, and found the solution. Where previously it lead to problems over and over again, I believe a combination of your hint (that cleanupThread must be in a different scope than the rest of the code) and some fiddling with the proc itself provided the solution. Literally doing this change: proc cleanupThread*() {.gcsafe, raises: [].}= {.cast(gcsafe).}: try: `=destroy`(getThreadDispatcher()) when defined(gcOrc): GC_fullCollect() # from orc.nim. Has no destructor. except Exception as e: echo "Exception during cleanup: ", e.repr Run Fixed the leak problems I had.