Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multithread singletons #46

Open
rafallus opened this issue Sep 8, 2019 · 6 comments
Open

Multithread singletons #46

rafallus opened this issue Sep 8, 2019 · 6 comments

Comments

@rafallus
Copy link
Contributor

rafallus commented Sep 8, 2019

I'm trying to access the VisualServer from a thread I created. So I'm using a code like this:

gdobj MyNode of Node:
  var thread: system.Thread[MyNode]
  method ready*() {.gdExport.} =
    createThread[MyNode](thread, threadProc, self)
  
  proc threadProc() {.thread.} =
    var meshRid = visual_server.meshCreate()

When I run the code, I have the following error:

ERROR: : Unhandled Nim exception: D:\Users\Godot\scripts\nim\src\script_lib\map\terrain\hex_terrain.nim(246) threadProc
D:\Users\Godot\scripts\nim\src_godotapi\visual_server.nim(4381) meshCreate
C:\Users\fallo.nimble\pkgs\godot-0.7.20\nim\godotnim.nim(374) getSingleton
C:\Users\fallo.nimble\pkgs\godot-0.7.20\nim\godotnim.nim(300) asNimGodotObject
C:\Users\fallo.nimble\pkgs\godot-0.7.20\nim\godotnim.nim(274) newNimGodotObject
D:\nim-0.20.2\lib\system\assertions.nim(27) failedAssertImpl
D:\nim-0.20.2\lib\system\assertions.nim(20) raiseAssert
D:\nim-0.20.2\lib\system\fatal.nim(39) sysFatal
Error: unhandled exception: C:\Users\fallo.nimble\pkgs\godot-0.7.20\nim\godotnim.nim(274, 9) not classRegistry.isNil [AssertionError]

At: godotnim.nim:908

Apparently when a new thread is created the visual server class is not registered (in the new thread context), and since the singleton is a threadvar, it is nil and can't be used.
Is there a way to solve this?

@zacharycarter
Copy link

I have a feeling you're going to run into a lot of issues with accessing foreign threads in Nim. Might want to take a look at the Nim docs around - setupForeignThreadGC

@endragor
Copy link
Member

This is not about accessing foreign threads, but rather accessing Godot from threads created in Nim.

This is currently not supported, but should be easy to implement by changing classRegistry to be a shared non-GC hash table rather than standard TableRef. Since classRegistry is populated only at initialization time and later accessed as read-only, it can be implemented without any locking.

@rafallus
Copy link
Contributor Author

but should be easy to implement by changing classRegistry to be a shared non-GC hash table

That's exactly what I did. The program is running just fine, but I'm concerned about memory leaks. I'm using a GC_fullCollect when the thread finishes, otherwise I have errors of PoolArrays and Godot objects that haven't been deallocated. I'm wondering if this is the correct way of dealing with the GC.

@endragor
Copy link
Member

I think that can be considered a bug in Nim - it doesn't run finalizers before deallocating thread's GC memory. It also doesn't do that in tearDownForeignThreadGc, which is a bug.

I'd recommend calling deallocHeap(runFinalizers = true, allowGcAfterwards = false) instead of GC_fullCollect(). That would ensure that everything is deallocated, but it has to be called right before thread exits. GC_fullCollect() may leave out things that are still on the stack, even if actually unused, because it has to be conservative about stack memory.

@endragor
Copy link
Member

Added issue in Nim repo about calling finalizers on thread exit: nim-lang/Nim#12192

@rafallus
Copy link
Contributor Author

Using deallocHeap is not working for me. On exit it throws the following error:

ERROR: : Unhandled Nim exception: C:\Users\fallo.nimble\pkgs\godot-0.7.22\nim\godotnim.nim(890) godot_gdnative_terminate
D:\nim-0.20.2\lib\system\gc_common.nim(432) deallocHeap
D:\nim-0.20.2\lib\system\gc_common.nim(420) prepareDealloc
C:\Users\fallo.nimble\pkgs\godot-0.7.22\nim\godotnim.nim(197) nimGodotObjectFinalizer
C:\Users\fallo.nimble\pkgs\godot-0.7.22\nim\godotnim.nim(169) unreference
C:\Users\fallo.nimble\pkgs\godot-0.7.22\godotinternal.nim(19) ptrCall
Error: unhandled exception: Could not access value because it is nil. [NilAccessError]

At: godotnim.nim:927
CrashHandlerException: Program crashed
Dumping the backtrace. Please include this when reporting the bug on https://github.com/godotengine/godot/issues
[0] _atomic_decrement_impl (D:\Users\fallo\Godot\Source\core\safe_refcount.cpp:67)
[1] atomic_decrement (D:\Users\fallo\Godot\Source\core\safe_refcount.cpp:128)
[2] SafeRefCount::unrefval (D:\Users\fallo\Godot\Source\core\safe_refcount.h:198)
[3] Reference::unreference (D:\Users\fallo\Godot\Source\core\reference.cpp:84)
[4] MethodBind0R<Reference,bool>::ptrcall (D:\Users\fallo\Godot\Source\core\method_bind.gen.inc:334)
[5] godot_method_bind_ptrcall (D:\Users\fallo\Godot\Source\modules\gdnative\gdnative\gdnative.cpp:70)
[6] ptrCall_J9clFxPbb8WTsAncRkkEw0Qgodotinternal (C:\Users\fallo.nimble\pkgs\godot-0.7.22\godotinternal.nim:20)
[7] unreference_j9bzXaMpeSQDwrtjw0a5Y7Q (C:\Users\fallo.nimble\pkgs\godot-0.7.22\nim\godotnim.nim:170)
[8] nimGodotObjectFinalizer_lqbHYZW6vM10ix5zsGGHyg (C:\Users\fallo.nimble\pkgs\godot-0.7.22\nim\godotnim.nim:197)
[9] prepareDealloc_fvhnFro5wEfzy879alizcUQ (D:\nim-0.20.2\lib\system\gc_common.nim:421)
[10] deallocHeap_7bQwx7xAIUIugRIQt0epPg (D:\nim-0.20.2\lib\system\alloc.nim:390)
[11] godot_gdnative_terminate (C:\Users\fallo.nimble\pkgs\godot-0.7.22\nim\godotnim.nim:893)
[12] GDNative::terminate (D:\Users\fallo\Godot\Source\modules\gdnative\gdnative.cpp:424)
[13] NativeScriptLanguage::~NativeScriptLanguage (D:\Users\fallo\Godot\Source\modules\gdnative\nativescript\nativescript.cpp:1045)
[14] NativeScriptLanguage::`scalar deleting destructor'
[15] memdelete (D:\Users\fallo\Godot\Source\core\os\memory.h:118)
[16] unregister_nativescript_types (D:\Users\fallo\Godot\Source\modules\gdnative\nativescript\register_types.cpp:72)
[17] unregister_gdnative_types (D:\Users\fallo\Godot\Source\modules\gdnative\register_types.cpp:307)
[18] unregister_module_types (D:\Users\fallo\Godot\Source\modules\register_module_types.gen.cpp:206)
[19] Main::cleanup (D:\Users\fallo\Godot\Source\main\main.cpp:2078)
[20] widechar_main (D:\Users\fallo\Godot\Source\platform\windows\godot_windows.cpp:164)
[21] _main (D:\Users\fallo\Godot\Source\platform\windows\godot_windows.cpp:184)
[22] main (D:\Users\fallo\Godot\Source\platform\windows\godot_windows.cpp:196)
[23] __scrt_common_main_seh (d:\agent_work\3\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288)
[24] BaseThreadInitThunk
-- END OF BACKTRACE --

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants