[ruby-trunk - Bug #9105][Open] callcc による不整合(例:Hash)

Issue #9105 has been reported by tarui (Masaya T.).


Bug #9105: callcc による不整合(例:Hash)

Author: tarui (Masaya T.)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: current: 2.1.0
ruby -v: ruby 2.1.0dev (2013-11-11 trunk 43647) [x86_64-linux]
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN

=begin
以下のコードを実行すると、
equire ‘continuation’
h = {1=>2,3=>4}
c = nil
f = false
h.each { callcc {|c2| c = c2 } }
unless f
f = true
c.call
end
h.each {|i| h.delete(1); p i}

以下のような結果になります。

[1, 2]
[false, false]
test.rb:10:in each': hash modified during iteration (RuntimeError) from test.rb:10:in

[false, false]自体はst_foreach_checkで全く機能していない
/* call func with error notice */
retval = (*func)(0, 0, arg, 1);
を消せばいいのですが、
RuntimeErrorが発生するのはcallccによりhash_foreach_ensureの実行が2重に行われて、
RHASH_ITER_LEV(hash)の管理が破綻してしまっている為です。

他の所でも容易に起こりうると思うのですが、未調査です。
&そもそもどう対処すべきでしょう?

=end

Issue #9105 has been updated by nagachika (Tomoyuki C.).

Status changed from Closed to Open

r43675 はマルチスレッドで同一の Hash を使っている場合に RHASH_ITER_LEV(hash)
の値が不正になることがあると思います。
以下のようなスクリプトを実行すると RHASH_ITER_LEV() が 0 に戻らなくなるので要素追加に失敗します。

h = {1=>2}
th1 = Thread.start{ h.each{ sleep 1 } }
sleep 0.1
th2 = Thread.start{ h.each { sleep 3 } }
th1.join
th2.join

h[5] = 6 # => can’t add a new key into hash during iteration
(RuntimeError)


Bug #9105: callcc による不整合(例:Hash)

Author: tarui (Masaya T.)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: current: 2.1.0
ruby -v: ruby 2.1.0dev (2013-11-11 trunk 43647) [x86_64-linux]
Backport: 1.9.3: UNKNOWN, 2.0.0: UNKNOWN

=begin
以下のコードを実行すると、
equire ‘continuation’
h = {1=>2,3=>4}
c = nil
f = false
h.each { callcc {|c2| c = c2 } }
unless f
f = true
c.call
end
h.each {|i| h.delete(1); p i}

以下のような結果になります。

[1, 2]
[false, false]
test.rb:10:in each': hash modified during iteration (RuntimeError) from test.rb:10:in

[false, false]自体はst_foreach_checkで全く機能していない
/* call func with error notice */
retval = (*func)(0, 0, arg, 1);
を消せばいいのですが、
RuntimeErrorが発生するのはcallccによりhash_foreach_ensureの実行が2重に行われて、
RHASH_ITER_LEV(hash)の管理が破綻してしまっている為です。

他の所でも容易に起こりうると思うのですが、未調査です。
&そもそもどう対処すべきでしょう?

=end