Issue #16342 has been reported by watson1978 (Shizuo Fujita). ---------------------------------------- Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する https://bugs.ruby-lang.org/issues/16342 * Author: watson1978 (Shizuo Fujita) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: * Backport: 2.5: UNKNOWN, 2.6: UNKNOWN ---------------------------------------- ## 再現環境 * Ruby 2.6.0 以降 * macOS 10.15 (試した環境) ## 問題の説明 macOS 上で Ruby 2.6.0 以降を使用した際に、拡張ライブラリ内で `fork()/exec()` で外部コマンドを実行したあと `waitpid()` をコールすると失敗するようになりました。 私がメンテナンスしている RMagick 利用している ImageMagick が PDF を処理する際にこのような処理を行っており、macOS + Ruby 2.6.0 以降で処理に失敗するようになり困っております。 https://github.com/rmagick/rmagick/issues/483 https://github.com/Watson1978/rmagick-issue483 に再現コードを用意しており、以下の様に実行していただくと macOS + Ruby 2.6.0 以降でエラー終了します。 ``` $ ./setup.sh $ ruby sample.rb $ ruby sample.rb Ruby v2.6.0 Error waitpid(): Interrupted system call ``` ``` $ ./setup.sh $ ruby ./sample.rb Ruby v2.6.5 Error waitpid(): Interrupted system call ``` Ruby 2.5.x 以下ですと期待通りに `WIFEXITED` のパスを通り正常に終了します。 ``` $ ./setup.sh $ ruby sample.rb Ruby v2.5.7 (1) WIFEXITED : status = 0 ``` ``` $ ./setup.sh $ ruby sample.rb Ruby v2.3.8 (1) WIFEXITED : status = 0 ``` 確認した限り、macOS 上だけでこの現象が発生します。 ## 再現コード https://github.com/Watson1978/rmagick-issue483 のレポジトリに以下と同様の再現コードをコミットしており、すぐに確認できるかと思います。 ``` #include <ruby.h> #include <unistd.h> VALUE sample_test(VALUE self) { int status = 0; int child_status = 0; pid_t child_pid = fork(); if (child_pid == 0) { char *const args[] = { "/bin/sleep", "1", NULL }; status = execvp(args[0], args); exit(0); } else { pid_t pid; pid = waitpid(child_pid, &child_status, 0); if (pid == -1) { status = -1; perror("Error waitpid()"); } else { if (WIFEXITED(child_status)) { // Expected path status = WEXITSTATUS(child_status); printf("(1) WIFEXITED : status = %d\n", status); } else if (WIFSIGNALED(child_status)) { status = -1; printf("(2) WIFSIGNALED : status = %d\n", status); } } } return INT2FIX(status); } void Init_sample(void) { VALUE rb_cSample = rb_define_class("Sample", rb_cObject); rb_define_method(rb_cSample, "test", sample_test, 0); } ``` -- https://bugs.ruby-lang.org/