Getting sigsegv when passing functions as parameters and building on M1
gergof opened this issue · 4 comments
I'm trying to build a library using node-addon-api on a M1 mac mini for x64 macs. The resulting addon works great on the newer MacOS versions, but it always crashes with a segfault on MacOS <= Big Sur.
I've managed to narrow down the problem to the cases where the code needs to interact with functions passed as parameters, but now I'm stuck and don't know how to proceed.
I have made a reproduction which always results in a segfault when built on the M1 mac, and always works as expected, when built on the x64 system.
The build system is an arm64 mac with MacOS 13.6 and the test system is an x64 system with MacOS 11.7.10.
This is the module itself:
// minrepr.mm
#include <napi.h>
Napi::Value helloWorld(const Napi::CallbackInfo& info) {
return Napi::String::New(info.Env(), "Hello World!");
}
Napi::Object Init(Napi::Env env, Napi::Object exports) {
exports.Set("helloWorld", Napi::Function::New(env, helloWorld));
exports.Set("workingHelloWorld", Napi::Function::New<helloWorld>(env));
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init);
The binding.gyp file:
{
"targets": [
{
"target_name": "MinRepr",
"conditions": [
["OS=='mac'", {
"sources": [
"minrepr.mm"
],
"libraries": [
"-lc++"
],
"xcode_settings": {
"CLANG_CXX_LANGUAGE_STANDARD": "c++17",
"GCC_ENABLE_CPP_EXCEPTIONS": "YES"
}
}]
],
"include_dirs": [
"<!@(node -p \"require('node-addon-api').include\")"
],
"libraries": [],
"dependencies": [
"<!(node -p \"require('node-addon-api').gyp\")"
],
"defines": [
"NAPI_DISABLE_CPP_EXCEPTIONS",
"NAPI_VERSION=<(napi_build_version)"
]
}
]
}
And I'm using the following command to build it:
prebuild --all -r napi --arch x64 --verbose
and have {"binary: {"napi_versions": [6]}}
set in my package.json.
The JS code I use for testing is the following:
const addon = require('./build/Release/MinRepr.node');
console.log('TEST');
console.log(addon);
console.log('Calling workingHelloWorld()');
console.log(addon.workingHelloWorld());
console.log('Calling helloWorld()');
console.log(addon.helloWorld());
console.log('Done');
The workingHelloWorld()
call works as expected no matter which system the code was built on, but helloWorld()
always results in a segfault when built on the M1 mac with the newer MacOS version.
When creating new functions it seems like I can do a workaround by creating the object in a different way, but I can't do the same when passing the main thread callback to ThreadSafeFunctions.
Versions:
- NodeJS: 18.18.0
- node-gyp: 9.4.0
- prebuild: 12.1.0
I'm going to attach the two .node files resulting from the two different systems:
- the one built on the M1 mac: https://cloud.systest.eu/s/qti9rXYD2qW6m7B
- the one build on the x64 mac with Big Sur: https://cloud.systest.eu/s/CAaGGBcARYnzyit
I've managed to fix the issue by downgrading from xcode 15 to xcode 14.3.1
@gergof I followed your steps, pasting the JS code into a file named test.js
, then ran node ./test.js
and it did not segfault. D'oh! I just read that it breaks on OSX <= Big Sur. Unfortunately I don't have the software to reproduce then.
tool | version |
---|---|
xcode | 15.0.0.0.1.1694021235 |
node-gyp | 9.4.1 |
node | 18.16.0 |
node-addon-api | 7.0.0 |
prebuild | 12.1.0 |
OSX | Sonoma |
Great that you found a workaround! If you have any more issues, please reopen this one or a new one.
I think I've run into the same problem.
I'm cross-compiling an add-on for x86_64 on an arm64 M1 Macbook running Sonoma, and it segfaults immediately when calling into it on an x86_64 machine running Catalina. It happens even with the smallest hello world example.
This is with Xcode 15.0.1. Just waiting for version 14.3.1 to download, and then I'll try with that.
EDIT: I can confirm that downgrading Xcode fixes it. @gergof, do you know if this Xcode issue is tracked somewhere?