Apache の mod_cgid と surrogate parent model について
monit のデッドロックを追っていた件から派生して、 pthread 全然知らんなーということで表紙がきもちわるいことで有名な(?) 『Pthreadsプログラミング』を読んでました。
- 作者: Bradford Nichols,Dick Buttlar,Jacqueline Proulx Farrel,榊正憲
- 出版社/メーカー: オライリー・ジャパン
- 発売日: 1998/05/01
- メディア: 大型本
- 購入: 4人 クリック: 52回
- この商品を含むブログ (21件) を見る
「5.5.1 スレッドのからのforkの呼び出し」の章で、スレッドから fork する際の注意点が書かれています。その中で 代理親モデル surrogate parent model という用語が気になったのでピックアップ。
代理親モデル surrogate parent model
代理親モデルを検討する 代理親モデル ( surrogate parent model) では、プログラムは初期化の時点でひとつの子プロセスをフォークする。子の唯一の目的は、オリジナルプロセスが別の子をフォークする必要がある時に、ある種の「代理親」として働くことである 『Pthreadsプログラミング』P214 から引用
これだけだと抽象的でよくわからないのですが、身近なところだと Apache の MPM worker で CGI を実行する際に使う mod_cgid というモジュールがこのモデルにのっとって実装されています。
ここで CGI の話をしよう
「え いとうさん いきなり CGI の話ですか 」 「それはあなた、わたしがホスティングやってる会社に勤めているからですよ」 「ろりぽっぷ!へてむる!ろりぽっぷ!へてむる!」
Apache の mod_cgid
mod_cgid を図解すると下記の様なモデルになっています
- Apache 起動時に cgidデーモンが fork される
- worker と cgidデーモンは UNIXドメインソケットでプロセス間通信する
- プロトコルはmod_cgidの独自実装
- マルチスレッドな worker に変わって cgidデーモンが fork + exec を担う
- cgid が 子プロセスを抱える = surrogate parent
CGIを実行中にプロセスツリーを取ってみると ↓ のようになります。
root 23330 0.0 0.4 173684 3928 ? Ss 17:42 0:00 /usr/sbin/httpd.worker apache 23332 0.0 0.2 173532 2584 ? S 17:42 0:00 \_ /usr/sbin/httpd.worker apache 23531 0.0 0.1 25568 1416 ? S 17:42 0:00 | \_ /usr/bin/perl /var/www/html/index.pl apache 23533 0.0 0.1 25568 1416 ? S 17:42 0:00 | \_ /usr/bin/perl /var/www/html/index.pl apache 23536 0.0 0.1 25568 1420 ? S 17:42 0:00 | \_ /usr/bin/perl /var/www/html/index.pl apache 23538 0.0 0.1 25568 1424 ? S 17:42 0:00 | \_ /usr/bin/perl /var/www/html/index.pl apache 23541 0.0 0.1 25568 1420 ? S 17:42 0:00 | \_ /usr/bin/perl /var/www/html/index.pl apache 23333 0.0 0.6 714552 5816 ? Sl 17:42 0:00 \_ /usr/sbin/httpd.worker apache 23334 0.0 0.6 714552 5860 ? Sl 17:42 0:00 \_ /usr/sbin/httpd.worker
プロセス名がみな同じなので区別がつきにくいですが、perl の子プロセスを生やしているのが cgid = surrogate parent なプロセスですね。cgid は Apacheが起動してマルチスレッド化する前にfork されるので子プロセスの中で一番若い pid を取得します。
surrogate parent
surrogate parent model で検索すると、リアルな子育て的なトピック( 代理の親が子育てするとあーだのこーだの...) ばっかりみつかってスレッドのお話の方はあんまりでてきません ...
一応 openldap (slapd) の ML が見つかったりはしましたが、どうも広く使われているような用語ではなさそうですね
名前はともかく、このようなモデルがあるのだなーというのが大事ですね。
mod_cgi と mod_cgid
「あれ、CGIってリクエストを受けている Aapcheプロセス自身が fork するんじゃなかったけ? 」というあなた、それは MPM prefork + mod_cgi ですね。mod_cgid とは別実装なのでした。
まとめ
マルチスレッドの制約があるため mod_cgid はやけに複雑な実装になってんるんだろうなー、と前々から気になってはいたのでしたが具体的な理由がよく分かって ませんでした。 本を読んで スレッド + fork 時の落とし穴を避けるためであることが明確になりすっきり。