You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Reproduced on V 0.5.1 (commit 99f141f in upstream master);
verified no relevant commits land between that and current
master b6dfae5. OS: macOS 26.4.1 ARM64.
Problem
A V -shared library built with the default Boehm GC is unusable from
host-spawned threads (Rust cargo workers, C# tasks, Java JNI threads)
because libgc aborts with "Collecting from unknown thread" whenever a
collection is triggered from a thread libgc has not been told about.
To register host threads, the binding must:
Call GC_allow_register_threads()once at module load (process-
level).
Call GC_register_my_thread(&stack_base)per thread before that
thread enters any V code.
Step 2 is inherently per-binding (the binding knows when it spawns a
thread). Step 1 is process-level and could be done by V itself.
Proposed fix
When emitting a -shared library and the default GC is Boehm, emit a
constructor that runs at dlopen time:
Every binding (Rust, C#, Java, …) is required to call cx_init() at
module load, and every binding's onboarding doc has a "remember to
call cx_init" footgun. With this V change, the cx_init export goes
away.
Why not GC-side?
bdwgc deliberately requires the host to opt in to thread-registration,
because for single-threaded users the cost of the lookup tables is
real. V already knows when it's building a multi-threaded -shared
library; emitting the constructor is the right layer.
Note
You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.
Problem
A V
-sharedlibrary built with the default Boehm GC is unusable fromhost-spawned threads (Rust cargo workers, C# tasks, Java JNI threads)
because libgc aborts with
"Collecting from unknown thread"whenever acollection is triggered from a thread libgc has not been told about.
To register host threads, the binding must:
GC_allow_register_threads()once at module load (process-level).
GC_register_my_thread(&stack_base)per thread before thatthread enters any V code.
Step 2 is inherently per-binding (the binding knows when it spawns a
thread). Step 1 is process-level and could be done by V itself.
Proposed fix
When emitting a
-sharedlibrary and the default GC is Boehm, emit aconstructor that runs at
dlopentime:That is the entire change. After it, host bindings only need the
per-thread call, which they need anyway.
Downstream evidence
CX currently exports its own
cx_initsymbol whose entire body isEvery binding (Rust, C#, Java, …) is required to call
cx_init()atmodule load, and every binding's onboarding doc has a "remember to
call cx_init" footgun. With this V change, the
cx_initexport goesaway.
Why not GC-side?
bdwgc deliberately requires the host to opt in to thread-registration,
because for single-threaded users the cost of the lookup tables is
real. V already knows when it's building a multi-threaded
-sharedlibrary; emitting the constructor is the right layer.
Note
You can use the 👍 reaction to increase the issue's priority for developers.
Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.