ruby-dev (Japanese) list archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-dev:50858] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
@ 2019-11-11 15:59 ` watson1978
  2019-11-11 16:45 ` [ruby-dev:50859] " mame
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: watson1978 @ 2019-11-11 15:59 UTC (permalink / raw)
  To: ruby-dev

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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-dev:50859] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
  2019-11-11 15:59 ` [ruby-dev:50858] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する watson1978
@ 2019-11-11 16:45 ` mame
  2019-11-12  4:52 ` [ruby-dev:50861] " watson1978
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: mame @ 2019-11-11 16:45 UTC (permalink / raw)
  To: ruby-dev

Issue #16342 has been updated by mame (Yusuke Endoh).


まったく試さずにエラーメッセージだけ見て回答してますが、waitpidがシグナルで割り込まれてEINTRで終わっているのだと思います。2.5で動いてたのは、たぶん偶然じゃないかと。 

https://abrakatabura.hatenablog.com/entry/2015/04/11/081256

のようにwhileしてみると良さそうな気がします。

----------------------------------------
Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
https://bugs.ruby-lang.org/issues/16342#change-82616

* 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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-dev:50861] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
  2019-11-11 15:59 ` [ruby-dev:50858] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する watson1978
  2019-11-11 16:45 ` [ruby-dev:50859] " mame
@ 2019-11-12  4:52 ` watson1978
  2019-12-16  8:03 ` [ruby-dev:50891] " mame
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: watson1978 @ 2019-11-12  4:52 UTC (permalink / raw)
  To: ruby-dev

Issue #16342 has been updated by watson1978 (Shizuo Fujita).


書き忘れていたのですが、 https://github.com/ruby/ruby/commit/48b6bd74e2febde095ac85d818e94c0e58677647 の変更を境にエラーになるようになり、それ以前ですと問題なく動いておりました。

----------------------------------------
Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
https://bugs.ruby-lang.org/issues/16342#change-82632

* 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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-dev:50891] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
                   ` (2 preceding siblings ...)
  2019-11-12  4:52 ` [ruby-dev:50861] " watson1978
@ 2019-12-16  8:03 ` mame
  2019-12-16 10:29 ` [ruby-dev:50892] " taca
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 7+ messages in thread
From: mame @ 2019-12-16  8:03 UTC (permalink / raw)
  To: ruby-dev

Issue #16342 has been updated by mame (Yusuke Endoh).

Status changed from Open to Rejected

頻度の問題で、2.6.0 以前でもこの問題は起きえます。多少人為的ですが、irbで↓のようにやれば Interrupted system call になりました。

```
irb(main):001:0> RUBY_VERSION
=> "2.5.7"
irb(main):002:0> trap(:WINCH) { }
=> "SYSTEM_DEFAULT"
irb(main):003:0> load "sample.rb" # ロード開始直後にターミナルをリサイズする
Ruby v2.5.7
Error waitpid(): Interrupted system call
=> true
```

ということで、少なくともその再現コードの waitpid(2) の使い方には問題があると思います。

私もタイマースレッド削除の変更をちゃんと理解してないんで大きなことはいえないんですが、調査してパッチを貰えれば検討できるかもしれません。(なんかのシグナルにSA_RESTARTを設定すればいいのかもしれないですが、他にも影響ありそう)

----------------------------------------
Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
https://bugs.ruby-lang.org/issues/16342#change-83153

* Author: watson1978 (Shizuo Fujita)
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-dev:50892] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
                   ` (3 preceding siblings ...)
  2019-12-16  8:03 ` [ruby-dev:50891] " mame
@ 2019-12-16 10:29 ` taca
  2020-01-29 15:16 ` [ruby-dev:50913] " watson1978
  2020-01-29 21:13 ` [ruby-dev:50914] " naruse
  6 siblings, 0 replies; 7+ messages in thread
From: taca @ 2019-12-16 10:29 UTC (permalink / raw)
  To: ruby-dev

Issue #16342 has been updated by taca (Takahiro Kambe).


解決策を持っているわけでも何でもないのですが、気になった事項です。
Process#forkに対応するRuby本体のprocess.cを読むとC言語のレベルでfork(2)を行う前にいくつかの前準備を行っています。一方、GitHubのsamble.cを拝見すると単純にfork(2)を呼び出していますので、そういった前準備を行わないわけなので、何が起きても不思議がない気がします。
fork(2)自体はProcess#forkを使用する様に変更できれば、回避できる問題の様に思えます。(そうできない事情もあるのだろうとは思いますが。)

----------------------------------------
Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
https://bugs.ruby-lang.org/issues/16342#change-83155

* Author: watson1978 (Shizuo Fujita)
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-dev:50913] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
                   ` (4 preceding siblings ...)
  2019-12-16 10:29 ` [ruby-dev:50892] " taca
@ 2020-01-29 15:16 ` watson1978
  2020-01-29 21:13 ` [ruby-dev:50914] " naruse
  6 siblings, 0 replies; 7+ messages in thread
From: watson1978 @ 2020-01-29 15:16 UTC (permalink / raw)
  To: ruby-dev

Issue #16342 has been updated by watson1978 (Shizuo Fujita).


問題の発端は https://github.com/rmagick/rmagick/issues/483 で macOS 環境だけ処理に失敗するケースが報告されたからですが、
サンプルのコード自体は私たちがメンテナンスしている RMagick で書いているのではなく、bridge 先の ImageMagick で書かれているものを抜粋したもので、
手を出しにくくて困っていた次第です。

ImageMagick を調べるしか無さそうな雰囲気ですね...

----------------------------------------
Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
https://bugs.ruby-lang.org/issues/16342#change-84110

* Author: watson1978 (Shizuo Fujita)
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [ruby-dev:50914] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
       [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
                   ` (5 preceding siblings ...)
  2020-01-29 15:16 ` [ruby-dev:50913] " watson1978
@ 2020-01-29 21:13 ` naruse
  6 siblings, 0 replies; 7+ messages in thread
From: naruse @ 2020-01-29 21:13 UTC (permalink / raw)
  To: ruby-dev

Issue #16342 has been updated by naruse (Yui NARUSE).


ImageMagickを調べると言うよりも、Rubyを調べる必要がある気はしますかね。

Kambeさんの仰っているとおり、Rubyではforkの前後に処理を入れています。
これは何をやっているかというと、そもそもforkというのはマルチスレッドやシグナルの配送と大変相性が悪く、
不用意にスレッドが起動している状態でforkを行うと異常な状態になる環境がいくつかありました。
Mac OS Xもその一つです。
それらへの対策としてrb_fork_rubyではforkの直前にタイマースレッドを止め、シグナルを…なんかいじって…、その後で満を持してforkを行い、
forkの後に改めて戻したりしてます。

なので、ImageMagickを呼び出す前と後にrb_fork_rubyでやっている前処理・後処理を追加すれば動くのではないかと思います

----------------------------------------
Bug #16342: macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する
https://bugs.ruby-lang.org/issues/16342#change-84115

* Author: watson1978 (Shizuo Fujita)
* Status: Rejected
* 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/

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-01-29 21:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <redmine.issue-16342.20191111155954@ruby-lang.org>
2019-11-11 15:59 ` [ruby-dev:50858] [Ruby master Bug#16342] macOS + Ruby 2.6.0 以降で拡張ライブラリ内での waitpid() コールに失敗する watson1978
2019-11-11 16:45 ` [ruby-dev:50859] " mame
2019-11-12  4:52 ` [ruby-dev:50861] " watson1978
2019-12-16  8:03 ` [ruby-dev:50891] " mame
2019-12-16 10:29 ` [ruby-dev:50892] " taca
2020-01-29 15:16 ` [ruby-dev:50913] " watson1978
2020-01-29 21:13 ` [ruby-dev:50914] " naruse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).