oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
74.29k stars 2.77k forks source link

NAPI Creating ExternalBuffer with Finalizer Segfaults #1826

Open cryptodeal opened 1 year ago

cryptodeal commented 1 year ago

What version of Bun is running?

0.5.0

What platform is your computer?

Darwin 22.2.0 arm64 arm

What steps can reproduce the bug?

Clone the following repo (branch: handle_as_external): https://github.com/cryptodeal/gen-napi

Ensure flashlight/arrayfire are installed: https://github.com/facebookresearch/shumai#install

Ensure switched to branch handle_as_external.

Build bindings: bun install

To reproduce the segfault from Bun:

bun buffer_issue.cjs

What is the expected behavior?

Running from node, it executes without Segfaulting.

To verify the same logic works from Node (v18.3.0):

node buffer_issue.cjs

What do you see instead?

Running bun buffer_issue.cjs it'll crash, sometimes w bus error or segmentation fault.

Output from lldb:

(base) cryptodeal@Jamess-MacBook-Pro gen-napi % lldb -- bun buffer_issue.cjs
(lldb) target create "bun"
Current executable set to '/Users/cryptodeal/.bun/bin/bun' (arm64).
(lldb) settings set -- target.run-args  "buffer_issue.cjs"
(lldb) r
Process 47582 launched: '/Users/cryptodeal/.bun/bin/bun' (arm64)
Process 47582 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=257, address=0x3fea5d6895604d1e)
    frame #0: 0x00005d6895604d1e
error: memory read failed for 0x5d6895604c00
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=257, address=0x3fea5d6895604d1e)
  * frame #0: 0x00005d6895604d1e
    frame #1: 0x0000000103a3b3b0 shumai_bindings.node`Napi::details::FinalizeData<void, void (*)(Napi::Env, void*, std::__1::vector<double, std::__1::allocator<double>>*), std::__1::vector<double, std::__1::allocator<double>>>::WrapperWithHint(napi_env__*, void*, void*) + 24
    frame #2: 0x00000001006544d0 bun`ExternalBuffer_deallocator + 36
    frame #3: 0x0000000100dda1c8 bun`JSC::ArrayBufferContents::~ArrayBufferContents() + 92
    frame #4: 0x0000000101555128 bun`WTF::DeferrableRefCounted<JSC::ArrayBuffer>::setIsDeferred(bool) + 100
    frame #5: 0x000000010155076c bun`JSC::Heap::runEndPhase(JSC::GCConductor) + 2712
    frame #6: 0x000000010154dc74 bun`JSC::Heap::runCurrentPhase(JSC::GCConductor, JSC::CurrentThreadState*) + 280
    frame #7: 0x000000010155eae4 bun`WTF::ScopedLambdaFunctor<void (JSC::CurrentThreadState&), JSC::Heap::collectInMutatorThread()::$_25>::implFunction(void*, JSC::CurrentThreadState&) + 36
    frame #8: 0x0000000101579410 bun`JSC::callWithCurrentThreadState(WTF::ScopedLambda<void (JSC::CurrentThreadState&)> const&) + 164
    frame #9: 0x000000010155e99c bun`JSC::Heap::collectInMutatorThread() + 96
    frame #10: 0x000000010155efd0 bun`JSC::Heap::stopIfNecessary() + 80
    frame #11: 0x0000000101ecebc4 bun`napi_adjust_external_memory + 76
    frame #12: 0x0000000103a11934 shumai_bindings.node`_tensorFromFloat64Buffer(Napi::CallbackInfo const&) + 304
    frame #13: 0x0000000103a3ffb4 shumai_bindings.node`napi_value__* Napi::details::WrapCallback<Napi::details::CallbackData<Napi::Value (*)(Napi::CallbackInfo const&), Napi::Value>::Wrapper(napi_env__*, napi_callback_info__*)::'lambda'()>(Napi::details::CallbackData<Napi::Value (*)(Napi::CallbackInfo const&), Napi::Value>::Wrapper(napi_env__*, napi_callback_info__*)::'lambda'()) + 60
    frame #14: 0x0000000103a3ff5c shumai_bindings.node`Napi::details::CallbackData<Napi::Value (*)(Napi::CallbackInfo const&), Napi::Value>::Wrapper(napi_env__*, napi_callback_info__*) + 28
    frame #15: 0x000000011800803c
    frame #16: 0x000000011808c1c4
    frame #17: 0x00000001180611fc

Additional information

Approach used here is the one recommended in the Node NAPI demos: https://github.com/nodejs/node-addon-examples/blob/main/typed_array_to_native/node-addon-api/typed_array_to_native.cc#L81

Jarred-Sumner commented 1 month ago

Pretty confident this has been fixed