non vorrei lavorare

ブログ名の通りです。javascript three.js mruby rust OCaml golang julialang blender

なぜ、waitpidをループ処理させるのか

おはようございます。先日、長男が明け方からお腹が痛いといい、朝起きてうんちが出るまで、 痛かったようで、おまけに熱も39度近くあったのですが、いざ、病院へ連れて行こうと再度 熱を測ったら、平熱。その日は保育園休ませ、様子を見ました。kjunichiです。

mruby-ioにissueを挙げたら思った以上に勉強させてもらえた件

前回のブログ記事への多くのブクマありがとうございました! まだ、前回の件で勉強になった事で書ききれていないことがあり、忘れないように記事にしておきます。

trusterdへのプルリク修行を指せてもらっているので、ここはひとつプルリクでもぼちぼち書き始めるかぁと 思ってもいたが、速攻で、対応されていた。

折角、対応して貰えたので、どういう対応なのか勉強させてもらおうと、コードを眺めた。

なんでdo-whileでwaitpidをチェックしているんだろ?

do {
      pid = waitpid(fptr->pid, NULL, 0);
} while (pid == -1 && errno == EINTR);

waitpidは子プロセスが終了するまで、待ってくれるからループする必要が 何であるのだろ?

学んだこと

いくつかのシステムコールは、コール実行中に割り込みを受け、erronoにEINTERを設定することが あるので、再度、システムコールを実行した方が良い場合がある。という事だった。

Linux で、write(2) や close(2) を呼んだらエラー EINTR が発生… - 人力検索はてな や closeがEINTRを返したらどうするべきか - Togetterまとめ

のやり取りで分かった。

なんで割り込み受けるのかを考えてみた

mruby-ioを使っているプログラムで、signalを扱う場合、waitpidをコールしていた場合signalを受けると、登録済みのシグナルハンドラの 実行後、このwaitpidコールが中断される。

すると、このままでは、子プロセスが終了しても、修正前と同様に残ってしまう。

これを避ける為に、waitpidの戻り値がEINTRで合ったら、再度実行しているようだ。

また、返されるpidの値はmanによると

If an error is detected or a caught signal
     aborts the call, a value of -1 is returned and errno is set to indicate the error.

とあるので、シグナルによる割り込みが発生した場合、-1がセットされるので、これも条件に含めていた。

mruby-ioのようなライブラリでは、さまざまな使われ方があり、これらの考えられうるユースケースのすべてにおいて、 正しく振る舞えるようにする必要があり、これを踏まえた実装であったのだ。

自前のアプリを作る際と比べ、ライブラリを作る際は、さらに多くの考慮が必要だという事が分かった。

勉強になりました。ありがとうございます。