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
Calling init, or other initialization functions twice accidentally can cause subtle bugs. It should check if it ever got initialized before and just return if it did.
Proposed Solution
In finalizeInit, perhaps a check like if (wasm != null) return wasm; as the first operation.
Alternatives
Well, personally I'd love to use wasm-bindgen generated modules similar to how they've been designed in the browser APIs: During initialization, you provide the imports and the initialization call gives you all exports. Imports and exports are tied to a specific wasm module instance.
However, I realize two things:
The current design is so that you can import wasm-bindgen generated projects in nodejs as if they were a normal library, without having to initialize anything.
When we called init twice, the issue we got was actually really subtle and annoying to debug:
We used the weak refs feature, i.e. FinalizationRegistrys were generated for us.
So in the main wasm-bindgen-generated project.js file (we used wasm-pack build --target web) we have following code generated:
Now, imagine you cause finalizeInit to run once, then the wasm variable will be set to some module.
In our code, we now continued running operations on our PublicNode. This causes them to be allocated and returned to JS and registered in their respective FinalizationRegistry.
Please note that the FinalizationRegistry closes over the wasm variable.
So now our code accidentally called finalizeInit again, which overwrites the last wasm value, and created a buch more PublicNodes.
When eventually enough PublicNodes were created, GC kicked in and deleted some older ones. These older ones then had their finalizers run and that caused the finalizers to be run on the "wrong" wasm memory. The ptr parameter wouldn't make sense in the new wasm instance.
Unfortunately that was really hard to debug, since finalizers only run when you've accumulated a bunch of garbage.
There's also other oddities like the error causing a "memory access out of bounds" (likely due to the ptr value being too big for the new wasm instance), but straight up causing a SIGBUS in nodejs on M1 Macs.
The text was updated successfully, but these errors were encountered:
Motivation
Calling
init
, or other initialization functions twice accidentally can cause subtle bugs. It should check if it ever got initialized before and just return if it did.Proposed Solution
In
finalizeInit
, perhaps a check likeif (wasm != null) return wasm;
as the first operation.Alternatives
Well, personally I'd love to use wasm-bindgen generated modules similar to how they've been designed in the browser APIs: During initialization, you provide the imports and the initialization call gives you all exports. Imports and exports are tied to a specific wasm module instance.
However, I realize two things:
Additional Context
When we called
init
twice, the issue we got was actually really subtle and annoying to debug:We used the weak refs feature, i.e.
FinalizationRegistry
s were generated for us.So in the main wasm-bindgen-generated
project.js
file (we usedwasm-pack build --target web
) we have following code generated:Now, imagine you cause
finalizeInit
to run once, then thewasm
variable will be set to some module.In our code, we now continued running operations on our
PublicNode
. This causes them to be allocated and returned to JS and registered in their respectiveFinalizationRegistry
.Please note that the FinalizationRegistry closes over the wasm variable.
So now our code accidentally called
finalizeInit
again, which overwrites the last wasm value, and created a buch morePublicNode
s.When eventually enough
PublicNode
s were created, GC kicked in and deleted some older ones. These older ones then had their finalizers run and that caused the finalizers to be run on the "wrong" wasm memory. Theptr
parameter wouldn't make sense in the newwasm
instance.Unfortunately that was really hard to debug, since finalizers only run when you've accumulated a bunch of garbage.
There's also other oddities like the error causing a "memory access out of bounds" (likely due to the
ptr
value being too big for the new wasm instance), but straight up causing a SIGBUS in nodejs on M1 Macs.The text was updated successfully, but these errors were encountered: