rclnodejs icon indicating copy to clipboard operation
rclnodejs copied to clipboard

Undefined symbol error using Electron >= 12 when receiving/deserializing arrays

Open n0wis opened this issue 3 years ago • 8 comments

Description When using any Electron version >= 12 (which include Node >= 14), receiving a message that includes a non-empty array causes a symbol lookup error: rclnodejs.node: undefined symbol: _ZN2v811ArrayBuffer3NewEPNS_7IsolateESt10shared_ptrINS_12BackingStoreEE

  • Library Version: 0.21.2
  • ROS Version: humble
  • Platform / OS: Ubuntu 22.04 LTS
  • Electron version: 19.0.8

Also tested on Ubuntu 20.04.3 LTS with galactic

Steps To Reproduce

  • npx create-react-app electron_app
  • npm i rclnodejs
  • Replace src/index.js with the following:
const { app, BrowserWindow } = require("electron");
const path = require("path");

const rclnodejs = require("rclnodejs");

const createWindow = () => {
  const mainWindow = new BrowserWindow();
  mainWindow.loadFile(path.join(__dirname, "index.html"));

  rclnodejs.init().then(() => {
    const node = new rclnodejs.Node("node_name");
    node.createSubscription(
      "sensor_msgs/msg/CompressedImage",
      "/image_raw/compressed",
      {},
      (msg) => {
        console.log(msg.header);
      }
    );
    node.spin();
  });
};
app.on("ready", createWindow);

  • npm start

Publish a suitable message that includes an array to the subscriber (in this example, it is a CompressedImage published via ros2 run image_publisher image_publisher_node image.jpg, but is reproducible with other kinds of arrays as well).

With Electron <= 11.5.3 everything works as expected. Also, empty arrays and raw messages do not cause the crash so I guess it is the deserialization.

Expected Behavior No crash / successful deserialization of the message.

Actual Behavior Crash with symbol lookup error: /tmp/electron_app/node_modules/rclnodejs/build/Release/rclnodejs.node: undefined symbol: _ZN2v811ArrayBuffer3NewEPNS_7IsolateESt10shared_ptrINS_12BackingStoreEE

n0wis avatar Jul 16 '22 09:07 n0wis

Thx for reporting this issue. The backingstore info looks somewhat familiar. Will investigate asap.

wayneparrott avatar Jul 18 '22 14:07 wayneparrott

We use the following #if, when nodejs > 12, we will use v8::BackingStore. From the crash log, it seems that the symbol is not found during runtime. @n0wis can you please double-check if it can reproduce on nodejs >= 14? I think we should have the unit test to cover this kind of case. https://github.com/RobotWebTools/rclnodejs/blob/4c23b0b01493a19f424fb85e7c1491b6402f25ed/src/rcl_bindings.cpp#L1320-L1330

minggangw avatar Jul 18 '22 15:07 minggangw

I probably should have emphasized that the error indeed does not occur when using "regular" Node >= 12, only the versions bundled with Electron crash. Unfortunately I know far too less about native Node.js modules to identify the cause of the error. It might be Electron after all?

I can file a bug report there if that is the more appropriate place.

Nonetheless, maybe the error can be prevented in this great package either way?

n0wis avatar Jul 18 '22 16:07 n0wis

Yes, I have noticed that you mentioned the env is Electron, but just to double-check it on pure nodejs. From our side, we can fall back to the non-BackingStore code when detecting it's a Electron env. @n0wis do you have any idea that the nodejs integrated into the Electron has any difference compared with a normal nodejs release?

minggangw avatar Jul 19 '22 03:07 minggangw

It does differ. Per the docs:

Native Node.js modules are supported by Electron, but since Electron has a different application binary interface (ABI) from a given Node.js binary (due to differences such as using Chromium's BoringSSL instead of OpenSSL), the native modules you use will need to be recompiled for Electron.

I followed the suggested steps to rebuild for the correct ABI version (which worked fine all along) but I could not resolve the missing symbol issue.

Unlike the my binary of pure nodejs, Electron is missing the mentioned symbol: nm -D node_modules/electron/dist/electron | grep _ZN2v811ArrayBuffer3NewEPNS_7IsolateESt10shared_ptrINS_12BackingStoreEE returns nothing.

However, nm -D node_modules/electron/dist/electron | grep _ZN2v811ArrayBuffer3NewEPNS yields:

0000000003233290 T _ZN2v811ArrayBuffer3NewEPNS_7IsolateEm
00000000032332e0 T _ZN2v811ArrayBuffer3NewEPNS_7IsolateENSt3__110shared_ptrINS_12BackingStoreEEE

If that's useful, following up with nm -C node_modules/electron/dist/electron | grep 00000000032332e0 leads to:

00000000032332e0 T v8::ArrayBuffer::New(v8::Isolate*, std::__1::shared_ptr<v8::BackingStore>)

The most similar function signature in the rebuild rclnodejs module I can find is: nm -C node_modules/rclnodejs/bin/linux-x64-106/rclnodejs.node | grep "ArrayBuffer::New("

U v8::ArrayBuffer::New(v8::Isolate*, std::shared_ptr<v8::BackingStore>)

I hope this is helpful and am happy to provide further information if required.

n0wis avatar Jul 19 '22 05:07 n0wis

I did some investigation about why there is ::__1 namespace, and it seems that you must depend on libstdc++, below is ldd result dumping the shared library dependencies for a normal nodejs binary. So would you check if your Electron version nodejs also depends on libstdc++?

~/proj/rclnodejs/build/Release$ ldd /home/minggang/.nvm/versions/node/v16.13.2/bin/node
        linux-vdso.so.1 (0x00007ffe96f77000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0c7dbac000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0c7d9ca000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0c7d87b000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0c7d860000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0c7d83d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0c7d64b000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0c7dbd6000)

minggangw avatar Jul 19 '22 16:07 minggangw

It does depend on libstdc++ as well. For completeness, here is the whole ldd output:

linux-vdso.so.1 (0x00007ffebc162000)
libffmpeg.so => /home/simon/code/autosens/electron/node_modules/electron/dist/libffmpeg.so (0x00007fc28cb80000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc28cb4f000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc28cb4a000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fc28cb45000)
libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x00007fc28cae3000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007fc28c9a9000)
libgio-2.0.so.0 => /lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007fc28c7d1000)
libnss3.so => /lib/x86_64-linux-gnu/libnss3.so (0x00007fc28c6a4000)
libnssutil3.so => /lib/x86_64-linux-gnu/libnssutil3.so (0x00007fc28c672000)
libsmime3.so => /lib/x86_64-linux-gnu/libsmime3.so (0x00007fc28c648000)
libnspr4.so => /lib/x86_64-linux-gnu/libnspr4.so (0x00007fc28c606000)
libatk-1.0.so.0 => /lib/x86_64-linux-gnu/libatk-1.0.so.0 (0x00007fc28c5dc000)
libatk-bridge-2.0.so.0 => /lib/x86_64-linux-gnu/libatk-bridge-2.0.so.0 (0x00007fc28c5a4000)
libX11.so.6 => /lib/x86_64-linux-gnu/libX11.so.6 (0x00007fc28c464000)
libX11-xcb.so.1 => /lib/x86_64-linux-gnu/libX11-xcb.so.1 (0x00007fc28c45f000)
libxcb.so.1 => /lib/x86_64-linux-gnu/libxcb.so.1 (0x00007fc28c435000)
libdbus-1.so.3 => /lib/x86_64-linux-gnu/libdbus-1.so.3 (0x00007fc28c3e5000)
libgdk_pixbuf-2.0.so.0 => /lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007fc28c3b5000)
libgtk-3.so.0 => /lib/x86_64-linux-gnu/libgtk-3.so.0 (0x00007fc28bb8c000)
libgdk-3.so.0 => /lib/x86_64-linux-gnu/libgdk-3.so.0 (0x00007fc28ba85000)
libpangocairo-1.0.so.0 => /lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007fc28ba73000)
libpango-1.0.so.0 => /lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007fc28ba0c000)
libcairo.so.2 => /lib/x86_64-linux-gnu/libcairo.so.2 (0x00007fc28b8e2000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc28b7fb000)
libXcomposite.so.1 => /lib/x86_64-linux-gnu/libXcomposite.so.1 (0x00007fc28b7f6000)
libXdamage.so.1 => /lib/x86_64-linux-gnu/libXdamage.so.1 (0x00007fc28b7f1000)
libXext.so.6 => /lib/x86_64-linux-gnu/libXext.so.6 (0x00007fc28b7dc000)
libXfixes.so.3 => /lib/x86_64-linux-gnu/libXfixes.so.3 (0x00007fc28b7d4000)
libXrandr.so.2 => /lib/x86_64-linux-gnu/libXrandr.so.2 (0x00007fc28b7c5000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007fc28b794000)
libdrm.so.2 => /lib/x86_64-linux-gnu/libdrm.so.2 (0x00007fc28b77e000)
libxkbcommon.so.0 => /lib/x86_64-linux-gnu/libxkbcommon.so.0 (0x00007fc28b737000)
libgbm.so.1 => /lib/x86_64-linux-gnu/libgbm.so.1 (0x00007fc28b726000)
libasound.so.2 => /lib/x86_64-linux-gnu/libasound.so.2 (0x00007fc28b623000)
libcups.so.2 => /lib/x86_64-linux-gnu/libcups.so.2 (0x00007fc28b583000)
libatspi.so.0 => /lib/x86_64-linux-gnu/libatspi.so.0 (0x00007fc28b549000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc28b529000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc28b301000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc29513a000)
libffi.so.8 => /lib/x86_64-linux-gnu/libffi.so.8 (0x00007fc28b2f4000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007fc28b27e000)
libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007fc28b275000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc28b259000)
libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007fc28b215000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007fc28b1e9000)
libplc4.so => /lib/x86_64-linux-gnu/libplc4.so (0x00007fc28b1e2000)
libplds4.so => /lib/x86_64-linux-gnu/libplds4.so (0x00007fc28b1dd000)
libXau.so.6 => /lib/x86_64-linux-gnu/libXau.so.6 (0x00007fc28b1d5000)
libXdmcp.so.6 => /lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007fc28b1cd000)
libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007fc28b106000)
libpng16.so.16 => /lib/x86_64-linux-gnu/libpng16.so.16 (0x00007fc28b0cb000)
libjpeg.so.8 => /lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007fc28b04a000)
libXi.so.6 => /lib/x86_64-linux-gnu/libXi.so.6 (0x00007fc28b034000)
libcairo-gobject.so.2 => /lib/x86_64-linux-gnu/libcairo-gobject.so.2 (0x00007fc28b028000)
libepoxy.so.0 => /lib/x86_64-linux-gnu/libepoxy.so.0 (0x00007fc28aef3000)
libfribidi.so.0 => /lib/x86_64-linux-gnu/libfribidi.so.0 (0x00007fc28aed7000)
libpangoft2-1.0.so.0 => /lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007fc28aebc000)
libharfbuzz.so.0 => /lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007fc28aded000)
libfontconfig.so.1 => /lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007fc28ada1000)
libXinerama.so.1 => /lib/x86_64-linux-gnu/libXinerama.so.1 (0x00007fc28ad9c000)
libXcursor.so.1 => /lib/x86_64-linux-gnu/libXcursor.so.1 (0x00007fc28ad90000)
libwayland-cursor.so.0 => /lib/x86_64-linux-gnu/libwayland-cursor.so.0 (0x00007fc28ad86000)
libwayland-egl.so.1 => /lib/x86_64-linux-gnu/libwayland-egl.so.1 (0x00007fc28ad81000)
libwayland-client.so.0 => /lib/x86_64-linux-gnu/libwayland-client.so.0 (0x00007fc28ad6f000)
libthai.so.0 => /lib/x86_64-linux-gnu/libthai.so.0 (0x00007fc28ad64000)
libpixman-1.so.0 => /lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007fc28acb9000)
libfreetype.so.6 => /lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007fc28abf1000)
libxcb-shm.so.0 => /lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007fc28abec000)
libxcb-render.so.0 => /lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007fc28abdd000)
libXrender.so.1 => /lib/x86_64-linux-gnu/libXrender.so.1 (0x00007fc28abce000)
libwayland-server.so.0 => /lib/x86_64-linux-gnu/libwayland-server.so.0 (0x00007fc28abb8000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc28a98c000)
libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007fc28a938000)
libavahi-common.so.3 => /lib/x86_64-linux-gnu/libavahi-common.so.3 (0x00007fc28a92a000)
libavahi-client.so.3 => /lib/x86_64-linux-gnu/libavahi-client.so.3 (0x00007fc28a914000)
libgnutls.so.30 => /lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007fc28a729000)
libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007fc28a6f2000)
libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007fc28a65b000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007fc28a643000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007fc28a616000)
libzstd.so.1 => /opt/ros/humble/lib/libzstd.so.1 (0x00007fc28a587000)
liblz4.so.1 => /lib/x86_64-linux-gnu/liblz4.so.1 (0x00007fc28a567000)
libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007fc28a55c000)
libgcrypt.so.20 => /lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007fc28a41e000)
libgraphite2.so.3 => /lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007fc28a3f5000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007fc28a3ec000)
libdatrie.so.1 => /lib/x86_64-linux-gnu/libdatrie.so.1 (0x00007fc28a3e3000)
libbrotlidec.so.1 => /lib/x86_64-linux-gnu/libbrotlidec.so.1 (0x00007fc28a3d5000)
libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007fc28a30a000)
libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007fc28a2d9000)
libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007fc28a2d3000)
libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007fc28a2c5000)
libp11-kit.so.0 => /lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007fc28a18a000)
libidn2.so.0 => /lib/x86_64-linux-gnu/libidn2.so.0 (0x00007fc28a169000)
libunistring.so.2 => /lib/x86_64-linux-gnu/libunistring.so.2 (0x00007fc289fbf000)
libtasn1.so.6 => /lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007fc289fa5000)
libnettle.so.8 => /lib/x86_64-linux-gnu/libnettle.so.8 (0x00007fc289f5f000)
libhogweed.so.6 => /lib/x86_64-linux-gnu/libhogweed.so.6 (0x00007fc289f17000)
libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fc289e95000)
libmd.so.0 => /lib/x86_64-linux-gnu/libmd.so.0 (0x00007fc289e88000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007fc289e60000)
libbrotlicommon.so.1 => /lib/x86_64-linux-gnu/libbrotlicommon.so.1 (0x00007fc289e3d000)
libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007fc289e36000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fc289e22000)

n0wis avatar Jul 19 '22 18:07 n0wis

Hmm... have no idea, but it's clear this is a linker issue

minggangw avatar Jul 20 '22 08:07 minggangw

The issue still persists with rcjlnodjs 0.21.4 and the most recent versions of Electron/Node...does anyone have further insight into the problem? I would be happy to help getting this bug closed.

n0wis avatar Dec 01 '22 09:12 n0wis

@n0wis Agree the undefined backingstore symbol error is still present with the latest Electron v22 and electron-rebuild v3.2. To get up to speed on this issue I ran a quick test with a super simple electron app on Ubuntu 22 with ROS2 Humble and rclnodejs 0.21.4. The app creates subscription to the sensor_msgs/msg/LaserScan message. ros2 run dummy_sensors dummy_laser is used to gen and publish laser messages. Boom! Same error :(

Electron v22 is based on nodejs 16.17.1. I confirmed that my test app succeeds when run outside of electron on node 16.17.

wayneparrott avatar Dec 01 '22 21:12 wayneparrott