fork以外の手段で子プロセスを生成する

 子プロセスで別のプログラムを走らせてその結果を受け取りたい時、C言語ではよくforkとexecの組み合わせを使う。しかし、考えてみれば、なんでforkでわざわざ一度プロセスをコピーして、子プロセス側で今まで使ってたfile descriporとかを始末してから次のプログラムを実行しないといけないんだろう。サーバなら自分自身をコピーする、というようなforkの使い方は自然なような気もするが、ちょっとした便利スクリプトを走らせて結果を受け取る、と言うような用途にはforkとexecは面倒くさい。直接新しいプロセスで新しいプログラムを実行してくれるようなシステムコールがあればいいのに。(popenは入力か出力のどちらかしかできないので力不足の場合がある。)
 そういった話をしていたら、シャチョーがLinuxのdo_forkはコピーする範囲をかなり詳細に指定できるヨと教えてくれた。これなら確かに、プレーンなプロセスを新しく使って、そこでプログラムを実行できる。しかし、これはOS依存なシステムコールなので、Linux以外でも使いたいプログラムでは避けたい。
 ということで探していたら、posix_spawnというシステムコールを見つけた。これはかなり望みに近いシステムコールで、引数として指定したファイルを新しいプロセスで実行してくれる。
 しかし、細かい挙動を見てみると、「If file_actions is a null pointer, then file descriptors open in the calling process shall remain open in the child process, except for those whose close-on- exec flag FD_CLOEXEC is set (see fcntl() ).」とあり、明示的に「こいつは新しいプロセスでは閉じておいてくれ」と頼んだfile descriptor以外は子プロセスでも共有されるみたい。ここがよくわからない。まぁ、別にそれですごく困ると言うことはないんだけど、file descriptorだけが共有されていて嬉しい場面と言うのが思いつかない。サーバを実装する時にはその方が嬉しいのかな、という気もするけれど、その他に嬉しい場面がまったく思いつかず、設計者の意図を自分が汲めていないのが、何だか気持ち悪い。
 ここからはちょっと余談になるんだけど、posix_spawnを探しているうちに、Secure File Descriptor Handlingという記事も見つけた。(ていうか、購読してるはずなんだけど、流し読みしてしまったみたい…。)要点を述べると、マルチスレッド環境下では、openで開いたfile descriptorにfcntlでFD_CLOEXECを設定する前に別スレッドからforkが行われる可能性があり、これはセキュリティの問題を引き起こし得るので、openする時点でO_CLOEXECをつける方がいいよ、という話。なんとも細かい話だが、信頼性のあるプログラムを書くためにはこのレベルできっちりとやっていかなければならないのだろう。心したい。
 そもそも、Solarisではマルチスレッドとforkの相性が悪いというのが社内で話題になっていたので調べ始めたのだが、調べていくうちに興味が発散してしまい、なにを調べてたんだか自分でもよくわからなくなってしまった。調べごとをするときは、対象をよく絞ってから行うべきですね。