https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112008-11-29T16:36:32ZRuby Issue Tracking SystemRuby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=18032008-11-29T16:36:32Zko1 (Koichi Sasada)
<ul><li><strong>Assignee</strong> set to <i>nobu (Nobuyoshi Nakada)</i></li></ul><p>=begin</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=19182008-12-11T04:23:33Zpragdave (Dave Thomas)dave@pragprog.com
<ul><li><strong>Priority</strong> changed from <i>Normal</i> to <i>5</i></li></ul><p>=begin<br>
ruby 1.9.1 (2008-12-10 revision 20602) [i386-darwin9.5.0] now says nothing—the code simply fails silently.</p>
<p>I've raised this one to 'high', because it will cause a lot of code that monitors background processes to fail silently, which seems dangerous.</p>
<p>Dave<br>
=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=19602008-12-11T11:56:53Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Assigned</i></li><li><strong>Assignee</strong> changed from <i>nobu (Nobuyoshi Nakada)</i> to <i>yugui (Yuki Sonoda)</i></li><li><strong>Priority</strong> changed from <i>5</i> to <i>6</i></li><li><strong>Target version</strong> set to <i>1.9.1 Release Candidate</i></li></ul><p>=begin</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=20382008-12-13T21:51:20Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul></ul><p>=begin<br>
Yuguiです。</p>
<p><a href="https://blade.ruby-lang.org/ruby-core/20448">[ruby-core:20448]</a>について、いくつかのことが起こっているように思います。<br>
まず、問題のコードを引用します。</p>
<p>Signal.trap(:CHLD) { puts "Child died" }<br>
fork && Process.wait</p>
<p>ところで、私の環境では例外は発生しません。ただし、Trapに渡したブロックも<br>
実行されません。<br>
% uname -a<br>
Darwin yugui-macbook.local 9.5.0 Darwin<br>
Kernel Version 9.5.0: Wed Sep 3 11:29:43 PDT 2008;<br>
root:xnu-1228.7.58~1/RELEASE_I386 i386<br>
% ./miniruby test.rb<br>
% ./miniruby test.rb</p>
<p>見てみると、timer_thread_functionに制御が渡ってきている気配がありませ<br>
ん。そこで、</p>
<p>diff --git a/thread_pthread.c b/thread_pthread.c<br>
index a23e772..b8f3d4e 100644<br>
--- a/thread_pthread.c<br>
+++ b/thread_pthread.c<br>
@@ -768,6 +768,7 @@ thread_timer(void *dummy)<br>
#endif<br>
timer_thread_function(dummy);<br>
}</p>
<ul>
<li>timer_thread_function(dummy);<br>
native_mutex_unlock(&timer_thread_lock);<br>
return NULL;<br>
}</li>
</ul>
<p>このようにして強制的に制御を渡してやると高い確率でChild diedが出力されま<br>
す。しかし、ここで高い確率でErrno::EINTRも発生するようになります。</p>
<p>Errno::EINTRはProcess.waitが発生させています。これは結局waitpid(2)がエ<br>
ラーを返すためのようです。そこで、添付のようなコードで実験してみると同じ<br>
ようにwaitpidがEINTRで失敗します。これはsigaction(2)のSA_RESTARTの項に書<br>
かれている挙動です。よって、次のようにして解決できます。</p>
<p>diff --git a/signal.c b/signal.c<br>
index 91aa7c4..b393280 100644<br>
--- a/signal.c<br>
+++ b/signal.c<br>
@@ -475,6 +475,9 @@ ruby_signal(int signum, sighandler_t handler)<br>
if (signum == SIGSEGV)<br>
sigact.sa_flags |= SA_ONSTACK;<br>
#endif<br>
+#ifdef SA_RESTART</p>
<ul>
<li>sigact.sa_flags |= SA_RESTART;<br>
+#endif<br>
if (sigaction(signum, &sigact, &old) < 0) {<br>
if (errno != 0 && errno != EINVAL) {<br>
rb_bug("sigaction error.\n");</li>
</ul>
<p>問題は2つに分かれるように思います。<br>
(1) OSのタイミング的にはRubyプロセスに届いたシグナルがSignal.trapで処理<br>
されないことは許されるであろうか? 許されないとすれば、スレッドの同期をど<br>
うとる?<br>
(VMの設計)</p>
<p>(2) 上の修正ではシグナルの種類によらずシステムコールを再開しているが、こ<br>
れは望ましいか。SIGCHLDに限定した方がよい?<br>
sleepなどはEINTRを無視して再開するように実装されているが、Rubyの<br>
Process.waitにおいて、シグナル受信で目覚める(そしてErrno::EINTR)ことは期<br>
待された挙動であろうか。<br>
(言語の設計と各プラットフォームの振る舞い)</p>
<p>--<br>
Yugui <a href="mailto:yugui@yugui.jp" class="email">yugui@yugui.jp</a><br>
<a href="http://yugui.jp" class="external">http://yugui.jp</a><br>
私は私をDumpする</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=20392008-12-13T22:00:22Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul></ul><p>=begin</p>
<blockquote>
<p>Errno::EINTRはProcess.waitが発生させています。これは結局waitpid(2)がエ<br>
ラーを返すためのようです。そこで、添付のようなコードで実験してみると同じ<br>
ようにwaitpidがEINTRで失敗します。これはsigaction(2)のSA_RESTARTの項に書<br>
かれている挙動です。よって、次のようにして解決できます。</p>
</blockquote>
<p>添付し忘れました。</p>
<p>--<br>
Yugui <a href="mailto:yugui@yugui.jp" class="email">yugui@yugui.jp</a><br>
<a href="http://yugui.jp" class="external">http://yugui.jp</a><br>
私は私をDumpする</p>
<p>#include <stdio.h><br>
#include <sys/wait.h><br>
#include <signal.h><br>
#include <errno.h></p>
<p>void sighandler(int signum) {}<br>
int main(void)<br>
{<br>
int status;<br>
pid_t pid;<br>
struct sigaction sigact, old;</p>
<pre><code> sigact.sa_sigaction = sighandler;
sigact.sa_flags = SA_SIGINFO;
if (sigaction(SIGCHLD, &sigact, &old)) {
fprintf(stderr, "sigaction failed: %s\n", strerror(errno));
}
if (pid = fork()) {
if (waitpid(pid, &status, 0) < 0) {
fprintf(stderr, "waitpid failed: %s\n", strerror(errno));
}
}
else {
}
return 0;
</code></pre>
<p>}<br>
=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=20422008-12-13T23:15:23Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul></ul><p>=begin<br>
Yuguiです。</p>
<p>Tanaka Akira さんは書きました:</p>
<blockquote>
<p>SA_RESTART でシステムコールを再開した場合、システムコールで<br>
ブロックしているスレッドを殺すのはどうやって実現するんですか?</p>
</blockquote>
<p>確かにそうですね。これは、SA_RESTARTをSIGCHLDに限定することで解決する問<br>
題でしょうか? それとも、他の手段(たとえば直近のシグナルの種類を見てシス<br>
テムコールを再呼び出し?)で適切なものがあるでしょうか。<br>
適当な解決策が分からないのが<a href="https://blade.ruby-lang.org/ruby-dev/20448">[ruby-dev:20448]</a>を投稿した理由です。</p>
<p>--<br>
Yugui <a href="mailto:yugui@yugui.jp" class="email">yugui@yugui.jp</a><br>
<a href="http://yugui.jp" class="external">http://yugui.jp</a><br>
私は私をDumpする</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=20542008-12-14T11:25:41Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul><li><strong>Assignee</strong> deleted (<del><i>yugui (Yuki Sonoda)</i></del>)</li></ul><p>=begin</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=21872008-12-21T00:08:37Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul><li><strong>Due date</strong> set to <i>12/24/2008</i></li></ul><p>=begin</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=22372008-12-22T12:53:18Zko1 (Koichi Sasada)
<ul><li><strong>Assignee</strong> set to <i>ko1 (Koichi Sasada)</i></li></ul><p>=begin</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=24362008-12-29T23:43:18Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul><li><strong>Due date</strong> changed from <i>12/24/2008</i> to <i>01/20/2009</i></li><li><strong>Priority</strong> changed from <i>6</i> to <i>Normal</i></li><li><strong>Target version</strong> changed from <i>1.9.1 Release Candidate</i> to <i>1.9.1 RC2</i></li></ul><p>=begin<br>
The reported bug consists of two parts.</p>
<p>The first one is that SIGCHLD causes Errno::EINTR. This problem was fixed by r21181.</p>
<p>The latter one is that the block passed to Signal.trap is never called. This is because both parent and child process are too short and the main thread of the parent process is terminated before it receives SIGCHLD. This is a bug of YARV and it is difficult to fix by 1.9.1 RC.</p>
<p>I think the block is called correctly when the program is enouogh complex as:<br>
Signal.trap(:CHLD) { puts "Child died" }<br>
fork {<br>
sleep 10<br>
exit<br>
}<br>
Thread.start {<br>
raise<br>
}<br>
Process.wait<br>
sleep 3</p>
<p>=end</p> Ruby master - Bug #727: Signal(CLD) seems not to work on OS Xhttps://redmine.ruby-lang.org/issues/727?journal_id=24372008-12-29T23:47:06Zyugui (Yuki Sonoda)yugui@yugui.jp
<ul><li><strong>Status</strong> changed from <i>Assigned</i> to <i>Closed</i></li><li><strong>% Done</strong> changed from <i>0</i> to <i>100</i></li></ul><p>=begin<br>
Applied in changeset r21181.<br>
=end</p>