Skip to content

Add emscripten guards to shared_library.c's dlopen path - #591

Open
Tobias-Fischer wants to merge 1 commit into
ros2:rollingfrom
Tobias-Fischer:fix/emscripten-shared-library-guards
Open

Add emscripten guards to shared_library.c's dlopen path#591
Tobias-Fischer wants to merge 1 commit into
ros2:rollingfrom
Tobias-Fischer:fix/emscripten-shared-library-guards

Conversation

@Tobias-Fischer

@Tobias-FischerTobias-Fischer commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Two related gaps in rcutils_load_shared_library() / rcutils_get_platform_library_name(), found while getting rcl_logging_implementation's dlopen-by-name backend selection working on emscripten-wasm32:

  • rcutils_get_platform_library_name() had no emscripten branch, so it always fell through with written == 0 ("failed to format library name"), regardless of which RCL_LOGGING_IMPLEMENTATION backend was requested. wasm32 side modules use the same lib<name>.so naming convention as Linux, so this reuses that branch.
  • The post-dlopen() path-resolution code took the _GNU_SOURCE branch (which emscripten's headers define) and called dlinfo(..., RTLD_DI_LINKMAP, ...). Emscripten's dlopen()/dlinfo() are a JS-backed shim, not glibc's, and don't support reading back a real struct link_map — so a successful dlopen() was getting treated as a failure once dlinfo() returned -1. The #else branch (reuse the path dlopen() was given) already covers this platform correctly, so this just excludes emscripten from the glibc-specific branch above it.

Both are narrow, additive #if/#elif guard changes — no behavior change on any existing platform.

Test plan

Verified end-to-end on a ROS 2 rolling + rmw_zenoh_pico + real-pthreads emscripten-wasm32 build (companion work in RoboStack/vinca#154 and RoboStack/ros-rolling#46): a wasm32 rclpy talker's logging initialization (rcl_logging_configurercl_logging_implementation → this dlopen path) now succeeds instead of aborting with "failed to load any logging implementations", regardless of which backend (rcl_logging_spdlog or rcl_logging_noop) is selected.

Full write-up

All the changes this required, across every repo, are documented together in Tobias-Fischer/ros2-emscripten-zenoh-demo — including a working rclcandrclpy browser demo verified end-to-end against a native zenohd router.

🤖 Generated with Claude Code

Two related gaps in rcutils_load_shared_library() / rcutils_get_platform_library_name(),
found while getting rcl_logging_implementation's dlopen-by-name backend
selection working on emscripten-wasm32:
- rcutils_get_platform_library_name() had no emscripten branch, so it always
fell through with written == 0 ("failed to format library name"),
regardless of which RCL_LOGGING_IMPLEMENTATION backend was requested.
wasm32 side modules use the same "lib<name>.so" convention as Linux.
- The post-dlopen path-resolution code took the _GNU_SOURCE branch (which
emscripten's headers define) and called dlinfo(..., RTLD_DI_LINKMAP, ...).
Emscripten's dlopen()/dlinfo() are a JS-backed shim, not glibc's, and
don't support reading back a real struct link_map -- so a successful
dlopen() got treated as a failure once dlinfo() returned -1. The #else
branch (reuse the path dlopen() was given) already covers this platform
correctly.
Verified end-to-end on a ROS 2 rolling + rmw_zenoh_pico + real-pthreads
emscripten-wasm32 build: a wasm32 rclpy talker's logging initialization
(rcl_logging_configure -> rcl_logging_implementation -> this dlopen path)
now succeeds instead of aborting with "failed to load any logging
implementations".
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Tobias-Fischer added a commit to Tobias-Fischer/ros-rolling that referenced this pull request Sep 9, 2026
- Bump the vinca pin to 325d0af, which also sets
CMAKE_SHARED_MODULE_CREATE_C/CXX_FLAGS (not just the SHARED-library
variants) -- CMake's MODULE library type, used by pybind11_add_module()
for every Python C extension (rclpy's own _rclpy_pybind11, and each
message package's rosidl_generator_py typesupport accessor), was linking
without USE_PTHREADS=1 even though its objects compiled with atomics
fine, producing a load-time "mismatch in shared state of memory" next to
the rest of a pthreads build. Invisible until something used
pybind11_add_module() -- found getting a live rclpy demo running.
- Add two Emscripten guards to patch/ros-rolling-rcutils.emscripten.patch
(upstreamed as ros2/rcutils#591) so rcl_logging_implementation's
dlopen-by-name backend selection works: rcutils_get_platform_library_name()
had no emscripten case (always "failed to format library name"), and the
post-dlopen path resolution took a dlinfo(RTLD_DI_LINKMAP) branch that
Emscripten's JS-backed dlopen doesn't support, treating a successful
dlopen() as a failure.
- Document a known gap (see pixi.toml comment): rosidl_typesupport_
microxrcedds_cpp's codegen doesn't handle service "_Event" messages, so
action_msgs/lifecycle_msgs/rcl_interfaces/rosgraph_msgs/statistics_msgs/
type_description_interfaces/micro_ros_msgs need a second, C-only rebuild
pass rather than the global STATIC_ROSIDL_TYPESUPPORT_CPP override this
task sets -- a real rclpy talker (not just rclc) verified end-to-end
through this same rmw_zenoh_pico pipeline surfaced this.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@Tobias-Fischer