[ruby-dev:51161] Re: Hash#shift を繰り返していると ruby が無応答になる。

From: Yusuke Endoh <mame@...>
Date: 2022-02-09 08:51:32 UTC
List: ruby-dev #51161
すみません、メールからチケットを作る仕組みがあるのを忘れてました。
それで作っておきました。

https://bugs.ruby-lang.org/issues/18578

続きはチケットの方に書こうと思います。

2022年2月9日(水) 17:44 Yusuke Endoh <mame@ruby-lang.org>:

> すばらしい再現例をありがとうございます!
> 次のパッチで直るとおもいます。
>
> ```
> diff --git a/st.c b/st.c
> index 53e9dc8320..07a083abb0 100644
> --- a/st.c
> +++ b/st.c
> @@ -1363,7 +1363,6 @@ st_shift(st_table *tab, st_data_t *key, st_data_t
> *value)
>             return 1;
>         }
>      }
> -    tab->entries_start = tab->entries_bound = 0;
>      if (value != 0) *value = 0;
>      return 0;
>  }
> ```
>
> 記録のためにチケットがほしいのですが、作っていただけますか?
>
> https://bugs.ruby-lang.org/projects/ruby-master/issues/new
>
> もしご面倒でしたら、代行して作成しますので言ってください。
>
>
> 2022年2月9日(水) 15:25 <ds14050@vvvvvv.sakura.ne.jp>:
>
>> はじめまして ds14050 といいます。最近スクリプトではなくインタープリタが
>> 原因で ruby の応答がなくなるケースに遭遇したと思いました。確認をお願いで
>> きますか。
>>
>> <<<以下再現スクリプト
>>
>> # ウチではだいたい 20 から 30 回で "empty?: true" を最後にして止まる。
>> # ウチの Ruby-2.5: ruby 2.5.5p157 (2019-03-15 revision 67260) [x64-mingw32]
>> # ウチの Ruby-2.7: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c)
>> [x64-mingw32]
>> # ウチの Ruby-3.1: ruby 3.1.0p0 (2021-12-25 revision fb4df44d16)
>> [x64-mingw-ucrt]
>>
>> H = {}
>> 100.times{|n|
>>      while H.size < n
>>          k = Random.rand 0..1<<30
>>          H[k] = 1 # たぶんここで止まる。
>>      end
>>      warn "size: #{H.size} before shifting."
>>      0 while H.shift
>>      warn "empty?: #{H.empty?}"
>> }
>> warn :exit
>>
>>  >>>
>>
>> Hash に要素を詰めて空にしてを 100 回繰り返すスクリプトです。3.1 を含む3
>> つのバージョンでほぼ確実に止まる(ruby.exe がビジー状態で終了しない)こと
>> を確認しています。2.5 より古い Ruby-1.9 では止まらずに最後まで実行が完了
>> しました。
>>
>> Hash を空にする方法として 0 while H.shift の代わりに H.shift until
>> H.empty? を選ぶと最後まで実行が完了するようになったことから呼び出すメ
>> ソッドを揃えて比較したところ、Hash が空になったあとの余分な Hash#shift
>> が何か悪さをしているように思えます。
>>
>> また、デバッグプリントを増やして確認したところ実際に停止しているのは
>> Hash#shift の行ではなく H[k] = 1 の行であるようでした。
>>
>> よろしくお願いします。
>>
>>

In This Thread

Prev Next