Bug #1848

Net::SSH hangs

Added by shyouhei (Shyouhei Urabe) almost 3 years ago. Updated about 1 year ago.

[ruby-dev:38971]
Status:Closed Start date:07/31/2009
Priority:Normal Due date:
Assignee:- % Done:

100%

Category:core
Target version:Ruby 1.8.7
ruby -v:1.8.7-p135 and later

Description

Revision r21165 以降、Net::SSHを使う場合(具体的にいうとCapistrano)で、スレッド切り替えがうまくいかないという報告を受けました
# また聞きでもうしわけない

https://capistrano.lighthouseapp.com/projects/8716/tickets/79
このへんが関係しているかも。してないかも。

再現方法

["localhost","localhost"].map {|h| Thread.new{Net::SSH.start(h, "foo")}}.each {|t| t.join}

proposed patch against 1.8.7

--- eval.c      (revision 24335)
+++ eval.c      (working copy)
@@ -11228,7 +11228,7 @@
            break;
        }
        if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
-           if (!next || next->priority < th->priority) {
+           if (!next || next->priority <= th->priority) {
                     th_found->status = THREAD_RUNNABLE;
                     th_found->wait_for = 0;

Associated revisions

Revision 24442
Added by akr almost 3 years ago

* eval.c (rb_thread_schedule): need select for WAIT_SELECT, even if already timeout. [ruby-dev:38971] (WAIT_DONE): defined for mark threads which can be runnable.

History

Updated by Tietew (Toru Iwase) almost 3 years ago

Tietew です。

これ、同じ箇所で刺さって困っていたのですが、このパッチで解決しました。
ruby_1_8ブランチです。ruby_1_8_7ブランチは未確認。

$ cap deploy
  * executing `deploy'
  * executing "*****"
    servers: ["server1.*****", "server2.*****"]
(ここで刺さる)


On Fri, 31 Jul 2009 16:00:27 +0900
In article <4a72968a4ec00_138122b2f16266e5@redmine.ruby-lang.org>
[[ruby-dev:38971] [Bug #1848] Net::SSH hangs]
Shyouhei Urabe <redmine@ruby-lang.org> wrote:

> Bug #1848: Net::SSH hangs
> http://redmine.ruby-lang.org/issues/show/1848
> 
> 起票者: Shyouhei Urabe
> ステータス: Open, 優先度: Normal
> カテゴリ: core, Target version: Ruby 1.8.7
> ruby -v: 1.8.7-p135 and later
> 
> Revision r21165 以降、Net::SSHを使う場合(具体的にいうとCapistrano)で、スレッド切り替えがうまくいかないという報告を受けました
> # また聞きでもうしわけない
> 
> https://capistrano.lighthouseapp.com/projects/8716/tickets/79
> このへんが関係しているかも。してないかも。
> 
> 再現方法
> 
> ["localhost","localhost"].map {|h| Thread.new{Net::SSH.start(h, "foo")}}.each {|t| t.join}
> 
> proposed patch against 1.8.7
> 
> --- eval.c      (revision 24335)
> +++ eval.c      (working copy)
> @@ -11228,7 +11228,7 @@
>             break;
>         }
>         if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
> -           if (!next || next->priority < th->priority) {
> +           if (!next || next->priority <= th->priority) {
>                      th_found->status = THREAD_RUNNABLE;
>                      th_found->wait_for = 0;
> 
> 
> ----------------------------------------
> http://redmine.ruby-lang.org

-- 
Tietew <tietew@tietew.net>
Blog: http://www.tietew.jp/
PGP: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA

Updated by shyouhei (Shyouhei Urabe) almost 3 years ago

パッチあててみましたがtest/test_timeout.rbがハングするようになりますね。
そこまでシンプルな話でもなさそう。

Updated by akira (akira yamada) almost 3 years ago

Shyouhei Urabe さんは書きました:
> パッチあててみましたがtest/test_timeout.rbがハングするようになりますね。
> そこまでシンプルな話でもなさそう。

よくわかってないまま試行錯誤を繰り返すのも
どうかとは思ったのですが、
たとえばこんな感じだとtest_timeout.rbは通るようです。

Index: eval.c
===================================================================
--- eval.c      (revision 24384)
+++ eval.c      (working copy)
@@ -11378,7 +11378,7 @@
            break;
        }
        if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
-           if (!next || next->priority < th->priority) {
+           if (!next || next->priority < th->priority || th == th_found && next->priority == th->priority) {
                 if (th == th_found) {
                     th_found->status = THREAD_RUNNABLE;
                     th_found->wait_for = 0;

# 今回はtest/runner.rbを実行して、パッチあり・なしで違いがでないところまでは確認しました。

-- 
やまだ

Updated by akira (akira yamada) almost 3 years ago

Tanaka Akira さんは書きました:
> Net::SSH の問題は手元では再現しないので、この問題の状況はよ
> くわかりません。

以下で、おそらく同じと思われる現象が起きます。
手元では実行ごとに毎回発生していますが、
もしかすると何度か実行すると〜かもしれません。

------------------------------------------------------------------------------
th = []

2.times do
  th << Thread.new do
    open("/dev/zero") do |i|
      loop do
        r, = IO.select([i], [], [], 0)
        if r
          p i.read(1)
          break
        end
      end
    end
  end
end

th.each {|t| t.join }
------------------------------------------------------------------------------

参考になるかどうかわかりませんがdebug printを入れてみました。
先頭が行番号です。

11249     /* Do the select if needed */
11250 fprintf(stderr,"%4d) need_select=%d\n",__LINE__,need_select);    if (need_select) {
11251         /* Convert delay to a timeval */
...
11267         n = select(max+1, &readfds, &writefds, &exceptfds, delay_ptr);
11268 fprintf(stderr,"%4d) n=%d\n",__LINE__,n);       if (n < 0) {
11269             int e = errno;
...
11361                     th_found = th;
11362 fprintf(stderr,"%4d) th_found=%d\n",__LINE__,th);                   found = 1;
11363                     break;
...
11369                     th_found = th;
11370 fprintf(stderr,"%4d) th_found=%d\n",__LINE__,th);                    found = 1;
11371                     break;
...
11386         }
11387 fprintf(stderr,"%4d) th=%d th_found=%d\n",__LINE__,th,th_found);        if ((th->status == THREAD_RUNNABLE || th == th_found) && th->stk_ptr) {
11388             if (!next || next->priority < th->priority) {
11389 fprintf(stderr,"%4d) next=th\n",__LINE__);              next = th;
11390             }

実行結果はこんな感じになります。
(使用したのはruby 1.8.8dev (2009-08-06 revision 24416) [i686-linux]です)

11250) need_select=1
11268) n=1
11370) th_found=142481000
11387) th=142326496 th_found=142481000
11389) next=th
11387) th=142481000 th_found=142481000
11250) need_select=1
11268) n=1
11370) th_found=142490464
11387) th=142481000 th_found=142490464
11389) next=th
11387) th=142326496 th_found=142490464
11387) th=142490464 th_found=142490464
11250) need_select=1
11268) n=1
11370) th_found=142481000
11387) th=142326496 th_found=142481000
11389) next=th
11387) th=142490464 th_found=142481000
11387) th=142481000 th_found=142481000
...

1.8.7-p35でも現象が発生します。1.8.7-p{72,134}と1.9.0-p0ではすぐに終了します。
-- 
やまだ

Updated by akr (Akira Tanaka) almost 3 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100
Applied in changeset r24442.

Updated by akira (akira yamada) almost 3 years ago

On 2009/08/07, at 23:47, Tanaka Akira wrote:
>> 以下で、おそらく同じと思われる現象が起きます。
>> 手元では実行ごとに毎回発生していますが、
>> もしかすると何度か実行すると〜かもしれません。
>
> すばらしい。再現しました。
>
> 直せたように思います。


ありがとうございます。
手元でも動作が確認できました。

-- 
やまだ

Also available in: Atom PDF