トップ «前の日記(2009-04-14) 最新 次の日記(2009-04-16)» 月表示 編集

日々の流転


2009-04-15 [長年日記]

λ. Ruby とプロセス: spawn について

akrさんのspawnの話を聴きにいった。 Ruby関係の参加者が沢山いるだろうと予想して行ったら、参加者はすごく少なかった。勿体無いなぁ。 私の知識は、想定される聴衆 level 2 「fork と exec なら大学で習った (shell を作る実習とか)」程度なので、「ほえー」という感じだったが、面白かった。

以下はメモ。

  • Rubyのプロセス起動のAPIは、帯に短しタスキに長し、というか短いものしかない。
  • fork/exec
    • 当時のシステムコールのデザイン。カーネルはアトミックなものを提供し、複雑なものはライブラリが提供する。
  • ruby 1.9 のタイマースレッド
    • スレッドの切り替え
    • シグナルはタイマースレッドが受ける
  • spawnで十分なのか?
    • コマンド実行にforkを使わなくていいじゃん、というのが今回の話。fork後execしないようなものはまた別の話。
  • 最終的なFDのマッピングを実現するために、一時的なFDが必要になる事があるので、FDの空きが足らないと動かない。ただ、Rubyは子プロセスでのエラーを通知するためにパイプを使っていて、そういう意味ではもともとダメなので気にしない。「もうだめなんで」「毒を喰らわば皿まで」
  • 余計なFDを閉じないとまずいことになる例
    • sortを呼び出してソートを行う場合、sortが(知らずに)書き込み側のFDを持ってると、読み込み側のFDをEOFまで読めない
  • popen4, popen5
    • pythonでもpopen5まで提案されたが、さすがにsubprocessという名前になった。
  • systemの実行中にinterruptを受けたら、子プロセスが死ぬだけで親は死なない
  • いつも使っているようなものでも、abstractionを変えるべきという一つの例
  • Windowsの実装はCreateProcessでうまくいくかと思ったら、親プロセスの属性を一時的にちょっと変えた状態でCreateProcessして、親プロセスを戻すという風になっている。
  • 親で属性を変えたときに安全に復帰できるか?
    • 例えばカレントディレクトリに戻れるか? (fchdirがあれば安全に戻れる)
    • 「race condition だから、バレなければOK」
  • 設定可能な属性は実は取捨選択してる。uid, gid周りは意図して避けた。特権のところはruby使うな。あと、シグナルのマスクとか。
  • 子プロセス側での属性設定、Windowsでも止まった状態で起動して、スレッドを注入して...とかやると出来る。
  • Windows ではFDは3番目以降は継承されない。カーネルオブジェクトは継承できるが、カーネルオブジェクトからFDへの対応が継承できない。前述のテクニックで、無理やり初期化すれば出来るらしい。しかし、WindowsにはFDを外から受け取るようなコマンド(e.g. valgrind)はそもそも無いので継承しても無意味。
  • 色々なプラットフォーム
    • MacOS : 複数のスレッドが動いているとexecがENOTSUPで失敗する。
    • FreeBSD 7 : スレッドを使っていると、forkだかexecだかが動からないらしい。
    • NetBSD 4 : fork したプロセスでスレッドが動かない。n:m のスレッド管理情報がメモリマップで管理されていて、共有されてまずいらしいとか。
    • NetBSD 5 : 動くらしい。
    • 動かないっていってくれる方がありがたいのでは?
  • 想定している前提
    • fork → exec ではどのOSでもサポートするであろう。
    • マルチスレッドの時にfork出来るか? さすがにシステム関数は使いたいから、動くだろう。
    • spawnはそこに毛が生えた程度をサポート
  • setenvはasyncsafeではないので、環境変数の設定は本当は親でやる必要があるかも。
Tags: ruby