Skip to content

Commit 695fcde

Browse files
mergify[bot]Tobias-Fischerahcorde
authored
Add emscripten guards to shared_library.c's dlopen path (ros2#591) (ros2#599)
* fix: add emscripten guards to shared_library.c's dlopen path 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". (cherry picked from commit a2d8f50) Signed-off-by: Alejandro Hernandez Cordero <ahcorde@gmail.com> Co-authored-by: Tobias Fischer <info@tobiasfischer.info> Co-authored-by: Alejandro Hernandez Cordero <ahcorde@gmail.com>
1 parent b28bfac commit 695fcde

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

‎src/shared_library.c‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,14 @@ rcutils_load_shared_library(
124124
goto fail;
125125
}
126126
lib->library_path = rcutils_strdup(image_name, lib->allocator);
127-
#elif defined(_GNU_SOURCE) && !defined(__QNXNTO__) && !defined(__ANDROID__) && !defined(__OHOS__)
127+
// Emscripten defines _GNU_SOURCE but its dlopen()/dlinfo() are a JS-backed
128+
// shim, not glibc's -- RTLD_DI_LINKMAP support (reading back a real
129+
// struct link_map) doesn't exist there. A successful dlopen() would
130+
// otherwise get treated as a failure once dlinfo() returns -1 below; the
131+
// #else branch already covers this correctly (it just reuses the path we
132+
// opened the library from, no introspection needed).
133+
#elif defined(_GNU_SOURCE) && !defined(__QNXNTO__) && !defined(__ANDROID__) && \
134+
!defined(__OHOS__) && !defined(__EMSCRIPTEN__)
128135
struct link_map * map = NULL;
129136
if (dlinfo(lib->lib_pointer, RTLD_DI_LINKMAP, &map) != 0) {
130137
RCUTILS_SET_ERROR_MSG_WITH_FORMAT_STRING("dlinfo error: %s", dlerror());
@@ -291,7 +298,12 @@ rcutils_get_platform_library_name(
291298

292299
int written = 0;
293300

294-
#if defined(__linux__) || defined(__QNXNTO__)
301+
// rcl_logging_implementation dlopens its backend (spdlog or noop) by name
302+
// at runtime via this function -- with no emscripten case it always falls
303+
// through with written == 0 ("failed to format library name"), regardless
304+
// of which backend RCL_LOGGING_IMPLEMENTATION selects. wasm32 side modules
305+
// use the same "lib<name>.so" naming convention as Linux.
306+
#if defined(__linux__) || defined(__QNXNTO__) || defined(__EMSCRIPTEN__)
295307
if (debug) {
296308
if (buffer_size >= (strlen(library_name) + 8)) {
297309
written = rcutils_snprintf(

0 commit comments

Comments
 (0)