Introduction
結果としては、多分、この記事は間違っている可能性が高いが、忘れないようにメモ。
事の経緯は、.NET Core 3.1 でビルドしたアプリが Ubuntu 16 上で動かなかったことから。
実行時に、依存関係が足りないと言われるも、ldd
で問題のライブラリの依存関係に問題は無かった。
そこでピンと来たのが、以前、開発メモ その190 .NET CoreでP/Invokeでの動的リンクに失敗したためLD_DEBUGで原因を調べてみる で書いたように、ライブラリが足りないのではなく、シンボルが読めないのでは?と思い下記で調べてみた。
1 | LD_DEBUG=libs dotnet test -c Release 2> error.log |
するとたくさん出るエラー。
1 | ... |
確かに、nm -D /lib/x86_64-linux-gnu/libssl.so.1.0.0 | grep BIO_up_ref
ってしても、問題のシンボルが見つからない。
でも、サポートされているディストリビューション のページでは Ubuntu 16.04 において、3.1 はサポート対象であると明記されている。
Why?
答えは下記にあった。
.NET Core 3.0 では、OpenSSL 1.0.x よりも OpenSSL 1.1.x が優先されます
Linux 用 .NET Core では、複数の Linux ディストリビューションで動作するため、OpenSSL 1.0.x と OpenSSL 1.1.x の両方がサポートされます。 .NET Core 2.1 および .NET Core 2.2 では、最初に 1.0.x が検索されてから、1.1.x にフォールバックされます。 .NET Core 3.0 では、最初に 1.1.x が検索されます。 この変更は、新しい暗号化標準のサポートを追加するために行われました。
うん、つまりlibssl 1.0.X
がデフォルトの Ubuntu 16 では、どうにもならないってことです。
手動で Libssl 1.1.X
を自分でビルドしてインストールすればいいんだろうけど。
でも、暗号系のAPI何か読んでいないのに、どうしてこんなエラーになったのかは疑問に残る。
予想だが、ビルドしたアプリが依存していたC++のライブラリ (ここではprotobuf) が OpenSSL を動的リンクしていて、そいつが .NET Core の依存する libssl の一致しなかったのでは、と考える。
However…
と思ったら、このエラーは関係ない可能性が高い。
というのも、 Ubuntu 20 における、 .NET Core 5.0 ではあるが、空のコンソールアプリケーションを作っても、似たようなシンボルが見つからないエラーが表示される。
1 | dotnet new console |
libssl や libicuuc でも同様のエラーが出ている事を見ると、エラーが出てもフォールバックで何事もなかったかのように処理をしている模様。
で、調査中だが、問題はC#からP/Invokeで呼出しているC++ライブラリがマズい可能性が高い。
自作のC++ライブラリを念のため別のC++から呼出す実行プログラムからリンクさせると、これがリンクの段階で動かない。
1 | /usr/bin/ld: XXXXX: hidden symbol `__cpu_indicator_init' in /usr/lib/gcc/x86_64-linux-gnu/5/libgcc.a(cpuinfo.o) is referenced by DSO |
このC++ライブラリの少し古いバージョンは問題なくリンクできて実行できた。
なので、差分を見ていって、問題を解決する。