Project

General

Profile

Actions

Bug #9072

closed

test_weakref.rb failure

Added by akr (Akira Tanaka) over 10 years ago. Updated over 10 years ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]
[ruby-dev:47788]

Description

test_weakref.rb を単独で動かすと、以下のように失敗します。

boron% ./ruby -v -e 'load("test/test_weakref.rb")'
ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]
test/test_weakref.rb:19: warning: assigned but unused variable - str
Run options:

Running tests:

[2/4] TestWeakRef#test_recycled = 0.01 s

  1. Failure:
    TestWeakRef#test_recycled [test/test_weakref.rb:25]:
    Expected "." to not be weakref_alive?.

Finished tests in 0.140466s, 28.4766 tests/s, 64.0724 assertions/s.
4 tests, 9 assertions, 1 failures, 0 errors, 0 skips

ruby -v: ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]

いろいろと疑問はあるのですが、
とりあえず weakref_alive? の結果を確認して見ようと思って
test/test_weakref.rb に以下のように p を入れてみました。

def test_recycled
weak, str = make_weakref
assert_nothing_raised(WeakRef::RefError) {weak.to_s}
assert_predicate(weak, :weakref_alive?)
ObjectSpace.garbage_collect
ObjectSpace.garbage_collect
assert_raise(WeakRef::RefError) {weak.to_s}
p weak.weakref_alive?
assert_not_predicate(weak, :weakref_alive?)
end

そうすると、以下のようになりました。

boron% ./ruby -v -e 'load("test/test_weakref.rb")'
ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]
test/test_weakref.rb:19: warning: assigned but unused variable - str
Run options:

Running tests:

[2/4] TestWeakRef#test_recyclednil
= 0.01 s

  1. Failure:
    TestWeakRef#test_recycled [test/test_weakref.rb:26]:
    Expected [] to not be weakref_alive?.

Finished tests in 0.164603s, 24.3009 tests/s, 54.6770 assertions/s.
4 tests, 9 assertions, 1 failures, 0 errors, 0 skips

ruby -v: ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]

weakref_alive? は nil を返しているようですがそれはともかく、
ここで奇妙なのは、Expected の次に出てくるのが "." から [] に変わっていることです。

さらにもうひとつ p を入れてみました。

def test_recycled
weak, str = make_weakref
assert_nothing_raised(WeakRef::RefError) {weak.to_s}
assert_predicate(weak, :weakref_alive?)
ObjectSpace.garbage_collect
ObjectSpace.garbage_collect
assert_raise(WeakRef::RefError) {weak.to_s}
p weak.weakref_alive?
p weak.weakref_alive?
assert_not_predicate(weak, :weakref_alive?)
end

そうすると以下のようになりました。

boron% ./ruby -v -e 'load("test/test_weakref.rb")'
ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]
test/test_weakref.rb:19: warning: assigned but unused variable - str
Run options:

Running tests:

[2/4] TestWeakRef#test_recyclednil
nil
= 0.01 s

  1. Failure:
    TestWeakRef#test_recycled [test/test_weakref.rb:27]:
    Expected {Object=>:never} to not be weakref_alive?.

Finished tests in 0.140746s, 28.4200 tests/s, 63.9450 assertions/s.
4 tests, 9 assertions, 1 failures, 0 errors, 0 skips

ruby -v: ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]

Expected の次に出てくるのは今度は {Object=>:never} になっています。

思うのですが、Expected の次に出てくるのがこのように変わるのはあまりに奇妙ではないでしょうか。

Updated by akr (Akira Tanaka) over 10 years ago

2013/11/2 akr (Akira Tanaka) :

Bug #9072: test_weakref.rb failure
https://bugs.ruby-lang.org/issues/9072

boron% ./ruby -v -e 'load("test/test_weakref.rb")'

おっと、load しているのに意味はないです。
(GC.stress = true とした前回のを再利用したからです。)

ファイル名だけを与えても再現します。

boron% ./ruby -v test/test_weakref.rb
ruby 2.1.0dev (2013-11-01 trunk 43510) [i686-linux]
test/test_weakref.rb:19: warning: assigned but unused variable - str
Run options:

Running tests:

[2/4] TestWeakRef#test_recycled = 0.01 s

  1. Failure:
    TestWeakRef#test_recycled [test/test_weakref.rb:25]:
    Expected "." to not be weakref_alive?.

Finished tests in 0.188558s, 21.2136 tests/s, 47.7307 assertions/s.
4 tests, 9 assertions, 1 failures, 0 errors, 0 skips

--
[田中 哲][たなか あきら][Tanaka Akira]

Updated by akr (Akira Tanaka) over 10 years ago

ちょっと追いかけたところ、ObjectSpace::WeakMap が、
入れた覚えのないオブジェクトを返すことがあるようです。

% ./ruby -ve '
wmap = ObjectSpace::WeakMap.new
keys = (1..10000).map {|i| i.to_s }
keys.each {|k| wmap[k] = "value" }
GC.start
keys.each {|k| p wmap[k] }
'|head -30
ruby 2.1.0dev (2013-11-04 trunk 43525) [x86_64-linux]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
nil
nil
[0, #<Method: ObjectSpace::WeakMap#finalize>]
nil
nil
nil
nil
-e:6:in p': Broken pipe (Errno::EPIPE) from -e:6:in block in '
from -e:6:in each' from -e:6:in '

Updated by akr (Akira Tanaka) over 10 years ago

もうちょっと調べて、いくらか少ない繰り返しで症状を発生させてみました。

% ./ruby -ve '
wmap = ObjectSpace::WeakMap.new
keys = []
1.upto(10) {|i|
GC.start
k = i.to_s
v = i.to_s
keys << k
wmap[k] = v
keys.each {|kk|
vv = wmap[kk]
next if vv == nil || vv == kk
p [kk, vv]
}
}
'
ruby 2.1.0dev (2013-11-05 trunk 43538) [x86_64-linux]
["1", [69905805532920]]
["1", [69905805532700]]
["2", "8"]
["5", ""1""]
["1", [69905805532620]]
["2", "8"]
["3", "9"]
["5", "9"]
["6", "["3", "9"]"]
["1", [69905805532560]]
["2", "8"]
["3", "9"]
["4", "10"]
["5", "9"]
["6", "10"]
["7", "["5", "9"]"]

キーと同じ値を入れたはずが、違うものが返ってくるのが観察できます。

finalizer が、想定されているほど早くには動かない、のかなぁ。

Actions #4

Updated by tarui (Masaya Tarui) over 10 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

This issue was solved with changeset r43539.
Akira, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0