*nix が wait 絡みのデッドロックを防ぐ仕組み

引き続き「Working With Unix Processes」を読んでいる。

サンプルで「デッドロックが起こりそう だけど、起こらない」コードが掲載されていた。次のスニペットは、そのサンプルを少し書き換えたものだ。

#!/usr/bin/env ruby

# ふたつの子プロセスをつくり、すぐに殺す
2.times do
  fork do
    abort "おしまい"
  end
end

# 最初の子プロセスを待ち、その後は3秒ほど寝る
# 寝ている間にもうひとつの子プロセスも終了する
puts Process.wait
sleep 3

# もう子プロセスは終了しているので、これはデッドロックするはずでは? => 実際はしない
puts Process.wait

コードのコメントに書いた通りなのだが、最後の Process.wait はデッドロックになっても不思議ではない… けど、実際にはデッドロックにならない。

カーネルには exit したプロセスの情報をキューに詰めておく機構があり、親プロセスは死んだ子プロセスの順にその情報を取得できる。だから、サンプルでの最後の Process.wait は実際には子プロセスの終了を待つのではなく、キューから「既に死んだ」子プロセスの情報を取得している。

ただ、子プロセスが存在しない「かつ」前述のキューにもデータが存在しないとき、Process.waitErrno::ECHILD 例外を起こす。

まあ、それはそうだよね。

コメントを残す

コメントを投稿するには、以下のいずれかでログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中