kubo39's blog

ただの雑記です。

preExecFunctionのはなし

preExecFunctionとはなにか

preExecFunctionはspawnProcessでfork-execのあいだに行う任意の処理を記述するためにある。

import std.process;
import std.stdio;

void main()
{
    Config config = {
        preExecFunction: () nothrow @nogc @trusted {
            import core.sys.posix.unistd;
            if (setsid() == -1)
                return false;
            return true;
        },
    };
    auto pid = spawnProcess(["make", "all"],
                            std.stdio.stdin,
                            std.stdio.stdout,
                            std.stdio.stderr,
                            null,
                            config);
    scope(exit) pid.wait;
}

これまでD言語のspawnProcessは子プロセス起動する前にやりたい操作のよくあるケースとして、リダイレクト・パイプ・カレントディレクトリの移動などは方法を提供していたが、任意の操作を行う方法を提供してこなかった。そのためsetsidやsetuidのような処理を呼ぶことができなかった。

こういった操作を行う方法を提供する手段として、

  1. fork-exec間に実行されるような任意の操作を関数として差し込む (Python, Rustなど)
  2. fork-exec間に行いたい操作を制限しておき、キーワード引数を使って将来的な拡張に対応する (Ruby)

といった方法があげられる。2の方法は結局使いたいときにそのバージョンで使えないこともあるが、非同期シグナル安全な関数以外を誤って使ってしまうことを防げる。 PythonやRustでは1の方法を使っているが、ドキュメントに危険性を書いている。

参考資料