Today I encountered a strangest error of them all. A missing library that exists.
A library that noone calls. Noone requires. Noone depends on it. Noone mentions in their src.
Yet when you remove it, the program breaks. How, on the deepest ponds of hell I ask, how?!
Cherry on the top: it is missing even when it exists. That’s kinda new.
It all began with a quest to gently push ROS into the world of lib64. That is, install ROS Lunar desktop on a pure 64bit Slackware. No multilib, no tinkering with “ln -s lib64 lib”, and so on. No tricks. Just patch the whole damn src directory and be done with it.
To be fair, after 3 days I am almost done. roscore works, communicates, does everything roscore should. Yet, when I call rviz, I get:
[ERROR] [1497042832.772480194]: PluginlibFactory: The plugin for class 'rviz/Orbit' failed to load. Error: Could not find library corresponding to plugin rviz/Orbit. Make sure the plugin description XML file has the correct name of the library and that the library actually exists.
And after that if I hit alt-tab I get Segmentation Fault.
Just for a moment I linked “ln -s lib64 lib” for compability and got:
Ok, so the compile was OK, just a misplaced library, but which one? lsof to the rescue:
lsof | grep rviz | grep "install_isolated/lib/"
and the result (part of):
rviz 17296 anil mem REG 8,1 7328320 62656812 /home/anil/ros_lunar/install_isolated/lib/librviz_default_plugin.so QXcbEvent 17296 17297 anil mem REG 8,1 7328320 62656812 /home/anil/ros_lunar/install_isolated/lib/librviz_default_plugin.so QDBusConn 17296 17308 anil mem REG 8,1 7328320 62656812 /home/anil/ros_lunar/install_isolated/lib/librviz_default_plugin.so
Ok, time to find out who exactly is calling this library:
ldd bin/* | grep librviz_default_plugin.so ldd lib64/* | grep librviz_default_plugin.so
Ok, time to grab the big guns, just in case I am missing anything
find ./ -type f -executable | xargs ldd > lista4.txt
NOTHING? Ok, it’s a source related thing.
2 hours later, no clue. I honestly don’t know why does this library end up being called from lib/ when it is quite correctly placed in lib64/ during the compile process.
Just to be sure, I checked if this is the only one causing trouble:
rm lib mkdir lib cp lib64/librviz_default_plugin.so lib/
Yeap, that’s the one.
I checked rviz, but after last patch it behaves nicely, the only mention of librviz_default_plugin can be traced to rviz/default_plugin/CMakeLists.txt with rviz_DEFAULT_PLUGIN_LIBRARY_TARGET_NAME variable, rviz-extras.cmake.in and a pair of rviz-extras.cmake + default_plugin_location.cmake (after compile) but they DON’T contain any visible information about explicit placement in the lib directory.
The tale is to be continued after a break and a cup of coffee.
(one dreadful morning later)
Ok, so it seems the Poco::SharedLibrary is getting a wrong path to the library itself, the name is being grabbed from plugin_description.xml:
class_loader.class_loader_private: Attempting to load library /home/anil/ros_lunar/install_isolated/lib/lib64/librviz_default_plugin.so on behalf of ClassLoader handle 0x1550d70... class_loader.class_loader_private: Attempting to load library /home/anil/ros_lunar/install_isolated/lib/lib64/librviz_default_plugin.so on behalf of ClassLoader handle 0x1589af0... class_loader.class_loader_private: Attempting to load library /home/anil/ros_lunar/install_isolated/lib/lib64/librviz_default_plugin.so on behalf of ClassLoader handle 0x15b0890...
Even if I modify the line, the lib part stays. I wonder, which instance is adding it here? The hunt goes on…
(two hours later)
Found it. Not class_loader’s fault, but again – catkin. When called upon:
the only paths returned ended with lib. So I modified find_in_workspaces.py a bit:
def find_in_workspaces(search_dirs=None, project=None, path=None, _workspaces=None, considered_paths=None, first_matching_workspace_only=False, first_match_only=False, workspace_to_source_spaces=None, source_path_to_packages=None): search_dirs = _get_valid_search_dirs(search_dirs, project) if 'libexec' in search_dirs: search_dirs.insert(search_dirs.index('libexec'), 'lib64') if 'lib' in search_dirs: search_dirs.insert(search_dirs.index('lib'), 'lib64') ...
and now catkin_find returns a correct collection of lib64 directories. At last.