萌えハッカーニュースリーダー

2025/08/27 00:45 Why did dlclose not unload the library?

出典: https://kishoreganesh.com/post/why-dl-close-did-not-work/
hakase
博士

やあ、ロボ子!今日は`dlclose`がライブラリをアンロードしない問題について話すのじゃ。

roboko
ロボ子

博士、こんにちは。`dlclose`がアンロードしないとは、一体どういうことでしょうか?

hakase
博士

ふむ、例えば`libA`(Rust)が`libB`(C++)に依存しているとするじゃろ? `progA`(C++)から`libA`を`dlopen`すると`libB`もロードされる。ここで`dlclose(libA)`をしても、`libA`はアンロードされるのに`libB`はアンロードされないことがあるんじゃ。

roboko
ロボ子

なるほど。それだと、次に`libA`をロードしたときに`libB`の初期化がうまくいかない、という問題が起きるのですね。

hakase
博士

そうなんじゃ!原因はいくつかあるぞ。まず、ELFに`-z nodelete`リンカフラグが指定されているか、`dlopen`のフラグで`RTLD_LAZY`を設定した場合じゃ。`STB_GNU_UNIQUE`を持つシンボルを含むライブラリは自動的に`NODELETE`になるんじゃ。

roboko
ロボ子

`NODELETE`フラグですか。それがついていると、アンロードされないのですね。

hakase
博士

`libstdc++.so`は多くのそのようなシンボルを含んでいて、`NODELETE`としてマークされることが多いんじゃ。もう一つの原因は、スレッドローカルストレージデストラクタじゃ。

roboko
ロボ子

スレッドローカルストレージデストラクタ、ですか?

hakase
博士

そうじゃ。ロードされたモジュールに登録されたスレッドローカルストレージデストラクタがあると、`dlclose`時にデストラクタが実行されないことがあるんじゃ。例えば、`libB`がRust関数を呼び出し、それがスレッドローカルストレージを使用している場合じゃな。

roboko
ロボ子

なるほど。それで、ロギングを有効にすると問題が解消されたというのは、どういうことでしょうか?

hakase
博士

良い質問じゃ!ロギングクレート(`env_logger`)がスレッドローカルストレージを使用し、TLSデストラクタを登録するため、`libA`も`dlclose`でアンロードされなくなるんじゃ。結果的に、`libA`と`libB`の状態が整合性を保つようになった、というわけじゃな。

roboko
ロボ子

ロギングが、アンロードの挙動に影響を与えるとは、驚きです。

hakase
博士

じゃろ?デバッグには`LD_DEBUG`環境変数が役立つぞ。これを使うと、ダイナミックローダーの動作を詳しく見れるんじゃ。ライブラリのロード、検索場所、アンロードのタイミング、`NODELETE`としてマークされているかどうかを確認できる。

roboko
ロボ子

`LD_DEBUG`、試してみます!スレッドローカルストレージデストラクタについては、どうすれば確認できますか?

hakase
博士

glibcの`_dlclose`にブレークポイントを設定して確認するのが良いじゃろう。これで、デストラクタが正しく実行されているか確認できるぞ。

roboko
ロボ子

なるほど、ありがとうございます!とても勉強になりました。

hakase
博士

どういたしまして。最後に一つ、ロボ子。`dlclose`がライブラリをアンロードしない問題は、まるで私が部屋を片付けないのと同じくらい厄介じゃな!

roboko
ロボ子

博士、それは違います!博士はいつも綺麗好きですよ!…たぶん。

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search