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

2025/10/17 13:04 Elixir/Ports and external process wiring

出典: https://mw.ludd.net/wiki/Elixir/Ports_and_external_process_wiring
hakase
博士

ロボ子、Elixirでrsyncライブラリを作ってる人がおるみたいじゃぞ。外部プロセスとの連携で色々苦労してるみたいじゃ。

roboko
ロボ子

rsyncですか。ファイル同期に使うあれですね。Elixirから外部プロセスを扱うのは、そんなに大変なんですか?

hakase
博士

`System.shell`とか`System.cmd`は、プロセスが終わるまでElixirのスレッドが止まってしまうからの。非同期に実行したいなら`Port.open`を使うのがミソじゃ。

roboko
ロボ子

`Port.open`ですか。rsyncの進捗状況はどうやって取得するんですか?

hakase
博士

rsyncには`--info=progress2`という便利なオプションがあるんじゃ。これを使うと、進捗状況が`:data`としてコールバックに送られてくる。終わったら`:exit_status`が来るぞ。

roboko
ロボ子

なるほど。rsyncの出力行が`:data`として送られてくるんですね。キャリッジリターン`\r`でターミナル上の表示を上書きするんですね。

hakase
博士

そうそう。Erlang/OTPの`gen_server`で`Port`呼び出しをラップすると、専用スレッドでrsyncを制御できるんじゃ。便利じゃろ?

roboko
ロボ子

確かに便利そうですが、記事には「`gen_server`が停止しても、外部の子プロセスは停止しない問題が発生」とありますね。

hakase
博士

`sleep 60`コマンドでも同じ現象が起きるらしいぞ。Elixirが終わってもプロセスが残ってしまうんじゃ。

roboko
ロボ子

標準入力が閉じられても、rsyncのようなデーモンプロセスは動き続けるんですね。対策はあるんですか?

hakase
博士

stdinのクローズを検知してSIGTERMを送るアダプターとか、`nohup`みたいなツールがあるみたいじゃな。Cプログラムでrsyncをラップして、`port_close`をSIGHUPに変換するshimも作ったらしいぞ。でも、SIGTERMが適切じゃな。

roboko
ロボ子

erlexecライブラリを参考に、外部プロセスのクリーンアップ処理を改善するアイデアもあるんですね。

hakase
博士

そうなんじゃ。BEAMコミュニティでは、外部プロセスの脆弱なクリーンアップはバグとして認識されてるからの。`port_close`をSIGTERMに適応させるPR#9453がレビュー待ちみたいじゃ。

roboko
ロボ子

どのシグナルを使うかはまだ未解決なんですね。HUP, TERM, KILLのどれが良いんでしょうか。

hakase
博士

Windowsには`erl_child_setup`レイヤーがないとか、プラットフォームによって実装が違うのも悩ましいところじゃ。

roboko
ロボ子

erlexecライブラリから、子プロセスのプロセスグループ全体をkillするオプションを導入するアイデアもあるんですね。それが一番確実かもしれませんね。

hakase
博士

ほんとじゃな。しかし、外部プロセスの扱いは奥が深いぞ。まるで、私の研究室の掃除みたいじゃ。いつも終わったと思ったら、どこかにゴミが残ってるんじゃから。

roboko
ロボ子

博士、それは掃除の仕方に問題があるのでは…?

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

Search