libCnoidROSPlugin.soの読み込みに失敗する

情報共有です.apt upgradeしたあるときからlibCnoidROSPlugin.soの読み込みができなくなりました.

Ctrl+Cで落とすとターミナルに以下の表示:

libgcc_s.so.1 must be installed for pthread_cancel to work
Aborted (core dumped)

原因の完全な特定はできていませんが,choreonoid_rosパッケージ内の,fmt::format に関するコードを全てコメントアウトすることで,当問題は消えました.

(undefined symbolの_ZTVN3fmt2v612format_errorEがfmtに関連しそうなことが推察されたため,この解消方法に至りました.)

sudo apt install libfmt-dev --reinstall

を実行し再ビルドを行った結果,choreonoid本体リポジトリ内のプラグインの読み込みエラーは消えました.一方でROSプラグインの読み込みには,format関連のコードを消さない限り,依然として失敗します.

Ubuntu 18.04 + ROS Melodic の環境で、apt-get update; apt-get upgradeを実行した上で、最新のソースコードで試してみたのですが、この問題が発生すること無く動作しました。

ただ事情によりcatkin cleanを実行した後にcatkin buildを実行して試しました。逆にcatkin cleanを実行してから再度ビルドしていただければ、問題が解決するかもしれません。

詳細は不明ですが、例えばアップグレードによってfmtライブラリのAPIかABIの互換性が失われて、fmtライブラリを使用するプログラムについては新しいバージョンで再ビルドしないと動作しないのかもしれません。これがcatkin cleanによって実現できた可能性があります。

catkin cleanしてもダメなようでしたら、お知らせください。まずはこちらの環境で再現できなければなりませんが…。

中岡さん,ありがとうございます.
改めてcatkin clean+catkin buildをし直しましたが,症状の改善は見られませんでした.

対症療法ができており緊急ではなく,また再現条件が不明なため,今の所ご対応はいただかなくて大丈夫です.(あくまでも情報共有の意図での投稿でした)

ふと思ったのですが、ROSはいろいろなパッケージがあって依存ライブラリもいろいろ入りますが、そのような依存ライブラリの共有ライブラリ(soファイル)は基本的に全てROSのlibディレクトリに入って、一括してパスが通るようなのですよね。なので何かのパッケージが、他でも使っている共有ライブラリの独自のバイナリなんかを入れてしまうと、そのライブラリに依存しているプログラムがUbuntu標準パッケージのバイナリではなくROSのバイナリと不本意にリンクされてしまって、それでうまく動かないと言ったこともひょっとしたらあるかもしれません。

今回のケースではfmtライブラリについてundefined symbolが出ていたとのことで、fmtライブラリの共有ライブラリの独自のバージョン(バイナリ)がROSの何かのパッケージでROSのlib以下にインストールされてて、そちらのパスが優先されてリンクされてしまって、それでこのような症状になっているのかもしれません。この状況は可能性としては有りうるのではないかと思います。

それかfmtライブラリ自体は入っていなくても、何か他のライブラリが内部でfmtライブラリをstaticリンクしていて、fmtライブラリのシンボルを内部にもっていたりして、そのライブラリがChoreonoidで利用するコントローラ等からリンクされていたりすると、まわりめぐってそのシンボルとリンクされてしまって、うまく動かないと言ったことも有りえます。Linuxで共有ライブラリを作ると、デフォルトでは全てのシンボルが外部公開になってしまうんですよね。この挙動は危険で、他のライブラリと干渉する危険性が高くなり、実際にそのような事故はよく起きています。これについてはシンボルを外部公開しないようにするGCC(やclangでも利用可能な)独自の記述があり、それを利用することでシンボルの公開は必要最低限なものに留めるというのが行儀のよいライブラリです。Choreonoidのライブラリもそのように実装しています。各モジュールに入っているexportdecl.hの定義とCNOID_EXPORTというマクロでこれを制御しています。ROSのプログラムの中にはこれを行っていないものもあるかもしれず、このような問題が起きているのかも知れません。

ありがとうございます,結論から申し上げるとご指摘のとおりでした.
Ubuntu 18.04 + ROS Melodic環境で,

cd /opt/ros
find . | grep -i fmt

を実行すると,

/melodic/lib/librosfmt.so
./melodic/lib/pkgconfig/rosfmt.pc
./melodic/lib/python2.7/dist-packages/rtshell/fmt.pyc
./melodic/lib/python2.7/dist-packages/rtshell/fmt.py
./melodic/include/rosfmt
./melodic/include/rosfmt/macros_generated.h
./melodic/include/rosfmt/rosfmt.h
./melodic/include/fmt
./melodic/include/fmt/printf.h
./melodic/include/fmt/format.h
./melodic/include/fmt/color.h
./melodic/include/fmt/posix.h
./melodic/include/fmt/core.h
./melodic/include/fmt/compile.h
./melodic/include/fmt/format-inl.h
./melodic/include/fmt/ostream.h
./melodic/include/fmt/locale.h
./melodic/include/fmt/safe-duration-cast.h
./melodic/include/fmt/ranges.h
./melodic/include/fmt/chrono.h
./melodic/share/rosfmt
./melodic/share/rosfmt/package.xml
./melodic/share/rosfmt/cmake
./melodic/share/rosfmt/cmake/rosfmtConfig.cmake
./melodic/share/rosfmt/cmake/rosfmtConfig-version.cmake

と怪しそうな感じがあり,sudo apt remove ros-melodic-rosfmtを実行してから再度findすると

./melodic/lib/python2.7/dist-packages/rtshell/fmt.pyc
./melodic/lib/python2.7/dist-packages/rtshell/fmt.py

と綺麗になりました.この状況で最新のmasterブランチのchoreonoid_rosをビルドし直したところ,無事リンクエラーなく正常動作することを確認できました.

rosfmt自体はROSの主要なライブラリが依存しているわけでもなく,恐らく私個人がrosmonというアプリケーションを試した際に入ってしまったものと思われます.

ご助言大変助かりました.

なるほどそうでしたか、解決したようでよかったです。

ただROS側で名前をlibrosfmt.soと変えているようなので、ちょっとどういうメカニズムで干渉してしまったのかわからないところもがありますが。実行時ではなくビルド時にこのlibrosfmtとリンクしてしまって、そこに必要なシンボル(関数)が実装されていなかったのかもしれませんね。

ちなみにビルド時は本来使用すべきライブラリとリンクできていて、実行時にのみこのような問題が生じるという場合でしたら、実行時にリンクするパスを共有ライブラリの中に埋め込むという方法で解決できることもあります。その場合はCMakeで ENABLE_INSTALL_RPATH_USE_LINK_PATHをONにしてビルドします。すると必ずビルド時のリンクした共有ライブラリを使用するようになります。

これはAGXDynamicsの最新版を使用するにあたっても使用するとよいオプションで、マニュアルでも説明もしています。
https://choreonoid.org/ja/documents/latest/agxdynamics/install/install-agx-ubuntu.html#agx
https://choreonoid.org/ja/documents/latest/agxdynamics/install/install-agxplugin.html