Rcutils: find_library: Prefer currently loaded libraries over searching `LD_LIBRARY_PATH`

Created on 25 Mar 2019  ·  22Comments  ·  Source: ros2/rcutils

At present, find_library drops straight into searching libraries along LD_LIBRARY_PATH, rather than first querying loaded libraries. One of the 3 current implementations:
https://github.com/ros2/rmw_implementation/blob/32c3de1/rmw_implementation/src/functions.cpp#L77

It'd be nice if this code instead preferred currently loaded libraries, to support application code that don't want the ability to switch DDS implementations (e.g. simplifying repro cases, etc.) at runtime, and instead RPATH link the appropriate libraries.

help wanted

Most helpful comment

Hmm, I'm starting to wonder why we need rcpputils::find_library_path() to begin with. If we simply provide rcutils_load_shared_library() or its rcpputils::SharedLibrary wrapper with a relative path, dlopen and LoadLibrary will search paths and yield loaded object files. Documentation for both suggests that already loaded object files will not be pulled in again. By doing this, RPATHs, LD_LIBRARY_PATHs, RUNPATHs, PATHs, and preloaded libraries would be honored by default.

CC @EricCousineau-TRI @wieset @clalancette.

All 22 comments

At this commit for this Bazel repro project, I can now either specify the RMW implementation at linking time, or defer to environment variables:
https://github.com/EricCousineau-TRI/repro/commit/cea11026722b340580257564dc49cb0f59b55178

@dirk-thomas I would find this extremely useful. Can I ask what (if any) evidence might sway you to consider this? :D

Can I ask what (if any) evidence might sway you to consider this?

Since the goal of having a distro is to ensure stability backports are for bug fixes only. Enhancements should target the next distro.

The first test packages of Dashing are targeted to be available in the first week of April.

Aye, sounds good. Will await the merge of https://github.com/ros2/rcpputils/issues/3, and then file this against the dev branch. Thanks!

We have a ros2 node that needs capabilities set via setcap which leads to LD_LIBRARY_PATH being omitted during execution. So we are setting RPATH in the binary to find shared libraries. However, as find_library_path relies on LD_LIBRARY_PATH the node fails with

terminate called after throwing an instance of 'rclcpp::exceptions::RCLError'
  what():  failed to initialized rcl init options: failed to find shared library of rmw implementation. Searched rmw_fastrtps_cpp, at /tmp/binarydeb/ros-eloquent-rmw-implementation-0.8.2/src/functions.cpp:130, at /tmp/binarydeb/ros-eloquent-rcl-0.8.3/src/rcl/init_options.c:55

If I understand correctly, the proposal by @EricCousineau-TRI would solve this problem. Any chance to get this functionality in the next release? Or any suggestions for a workaround?

@EricCousineau-TRI are you planning to iterate on this?

If I understand correctly, the proposal by @EricCousineau-TRI would solve this problem.

@wieset How would it solve the problem if the library you are trying to find / load isn't already loaded?

@ivanpauno Probably not anytime in the near future (~6mo to 1yr), unfortunately :(

@dirk-thomas I looked at @EricCousineau-TRI's example code and you are right, it would not solve my problem if the library isn't already loaded. I guess I could link it at build time so that it gets loaded at program startup?

However, to preserve loading at run time, I see two options: Either RPATH would have to be searched, which I can set through CMAKE_INSTALL_RPATH, or another environment variable could be used instead of LD_LIBRARY_PATH, e.g. RMW_LIBRARY_PATH. I mentioned both those options in https://github.com/ros2/rcpputils/issues/40.

@wieset Customizing your build to use rpath for this use case sounds like the way to go.

@dirk-thomas Agreed, and I am already using RPATH to load all other libraries. But that doesn't get me around the fact that find_library_path() for the rmw library currently doesn't look there. Or am I missing something?

But that doesn't get me around the fact that find_library_path() for the rtw library currently doesn't look there.

You are right. I missed the context on this ticket.

I wonder if it makes sense to introduce a separate environment variable for this or if you should just make sure when running executables as root to set the existing environment variables yourself explicitly.

As far as I understand, LD_LIBRARY_PATH is ignored completely for setcap / setuid executables, so setting it myself wouldn't help unfortunately. See http://man7.org/linux/man-pages/man8/ld.so.8.html

Not sure if introducing a new env var like ROS_LIBRARY_PATH to bypass that security limitation is a good idea. ld only wouldn't filter that because it doesn't know about it and it ignores LD_LIBRARY_PATH due to security considerations.

Please feel free to propose PRs to add this enhancement (as indicated by the "help wanted" label).

Will look into into it!

Created a pull request at https://github.com/ros2/rcpputils/pull/44

FWIW @hidmic, @iantheengineer, and I are starting to discuss this with other folk at TRI. First towards our internal uses, then towards integration with things like Drake.

Hmm, I'm starting to wonder why we need rcpputils::find_library_path() to begin with. If we simply provide rcutils_load_shared_library() or its rcpputils::SharedLibrary wrapper with a relative path, dlopen and LoadLibrary will search paths and yield loaded object files. Documentation for both suggests that already loaded object files will not be pulled in again. By doing this, RPATHs, LD_LIBRARY_PATHs, RUNPATHs, PATHs, and preloaded libraries would be honored by default.

CC @EricCousineau-TRI @wieset @clalancette.

Alright, see #320 and connected PRs for a first stab at this. @wieset this should (indirectly) solve your issues as well. These changes render rcpputils::find_library_path obsolete though (for usage in core packages).

@hidmic Now that we've landed #320 and friends, can we close this out?

Indeed we can. Thanks for the bump!

Thanks a lot @hidmic, I think this gets me halfway there. RUNPATH still needs to get populated properly. I'll continue the discussion with @clalancette in https://github.com/ros2/rcpputils/pull/44.

Was this page helpful?
0 / 5 - 0 ratings