Project

General

Profile

Actions

Bug #4480

closed

Thread-local variables issue: Thread#[] returns nil when called first time

Added by dre3k (Andrei Kulakov) over 13 years ago. Updated over 13 years ago.

Status:
Closed
Target version:
ruby -v:
-
Backport:
[ruby-core:<unknown>]

Description

=begin
In ruby 1.9.2p180
t = Thread.new do
Thread.current[:var] = "var"
Thread.stop
end

p t[:var] #=> nil
p t[:var] #=> "var"

In ruby 1.8.7
p t[:var] #=> "var"
p t[:var] #=> "var"
=end


Files

thread_rdoc_fix.patch (1.14 KB) thread_rdoc_fix.patch dre3k (Andrei Kulakov), 03/12/2011 08:26 PM
Actions #1

Updated by robertgleeson (Robert Gleeson) over 13 years ago

=begin
Hi Andrei,

I don't think this is a bug. You should call Thread#join before you call Kernel.p.
Your thread may or may not not have been run by the time you call Kernel.p, and you may get
inconsistent results such as t[:var] being nil sometimes, and being "var" at other times.

Thanks,
Rob
=end

Actions #2

Updated by dre3k (Andrei Kulakov) over 13 years ago

=begin
Hi Robert,

Thanks a lot. You are totally right about Thread#join.

But what the solution in my particular case, how do I get thread-local variable when Thread.stop called within a thread.
t = Thread.new do
Thread.current[:var] = "var"
Thread.stop
end

t.join

p t[:var]
p t[:var]

yiedls
threads.rb:6:in join': deadlock detected (fatal) from threads.rb:6:in '
and it's supposed to be like that.

Apologies if it's a stupid question.
=end

Actions #3

Updated by dre3k (Andrei Kulakov) over 13 years ago

=begin
I also wanted to say this is rdoc's example of Thread#[] the one that tricked me.

Right now this is:
a = Thread.new { Thread.current["name"] = "A"; Thread.stop }
b = Thread.new { Thread.current[:name] = "B"; Thread.stop }
c = Thread.new { Thread.current["name"] = "C"; Thread.stop }
Thread.list.each {|x| puts "#{x.inspect}: #{x[:name]}" }
produces:
#<Thread:0x401b3b3c sleep>: C
#<Thread:0x401b3bc8 sleep>: B
#<Thread:0x401b3c68 sleep>: A
#<Thread:0x401bdf4c run>:

But on some slower machine it will produce different results.

Maybe it's better to change this example to something like following:

a = Thread.new { Thread.current["name"] = "A" }
b = Thread.new { Thread.current[:name] = "B" }
c = Thread.new { Thread.current["name"] = "C" }

Thread.list.each do |thr|
thr.join unless thr == Thread.main
puts "#{thr.inspect}: #{thr[:name]}"
end
produces:
#<Thread:0x88bf918 run>:
#<Thread:0x88b22cc dead>: A
#<Thread:0x88b2290 dead>: B
#<Thread:0x88b2254 dead>: C

Or some other more consistent example than current.
=end

Updated by naruse (Yui NARUSE) over 13 years ago

  • Status changed from Open to Assigned
  • Assignee set to nahi (Hiroshi Nakamura)

Updated by ko1 (Koichi Sasada) over 13 years ago

  • ruby -v changed from ruby 1.9.2p180 (2011-02-18 revision 30909) [i686-linux] to -

(2011/06/26 18:24), Yui NARUSE wrote:

In ruby 1.9.2p180
t = Thread.new do
Thread.current[:var] = "var"
Thread.stop
end

p t[:var] #=> nil
p t[:var] #=> "var"

In ruby 1.8.7
p t[:var] #=> "var"
p t[:var] #=> "var"

It seems intentional. When the first access, the Thread.current[:var]
is not initialized (not reached the initialization code).

--
// SASADA Koichi at atdot dot net

Updated by nahi (Hiroshi Nakamura) over 13 years ago

On Sun, Jun 26, 2011 at 20:12, SASADA Koichi wrote:

It seems intentional.  When the first access, the Thread.current[:var]
is not initialized (not reached the initialization code).

You're right. I took this ticcket since it would be a RDoc issue.

Updated by nahi (Hiroshi Nakamura) over 13 years ago

  • Category set to doc
  • Target version changed from 1.9.2 to 1.9.3

Updated RDoc at r32260 based on Andrei's patch. I just wanted to remove Thread.main thing to concentrate Thread#[] behavior. Thanks!

Updated by nahi (Hiroshi Nakamura) over 13 years ago

  • Status changed from Assigned to Closed
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0Like0Like0Like0Like0