Forum: Ruby-core [Bug #1717] Thread local variables not visible from within a Fiber

Posted by Muhammad Ali (Guest)
on 2009-07-02 22:38
(Received via mailing list)
Bug #1717: Thread local variables not visible from within a Fiber
http://redmine.ruby-lang.org/issues/show/1717

Author: Muhammad Ali
Status: Open, Priority: Normal
Category: core
ruby -v: ruby 1.9.1p129 (2009-05-12 revision 23412) [i686-linux]

# Given the following:

Thread.current[:x] = 1

Fiber.new{Thread.current[:x]}.resume # => nil

# returns nil when it should return 1
# even though Thread.current returns the same object
Posted by Roger Pack (Guest)
on 2009-07-12 05:44
(Received via mailing list)
Issue #1717 has been updated by Roger Pack.


does this work in trunk?
=r
----------------------------------------
http://redmine.ruby-lang.org/issues/show/1717
Posted by Yusuke ENDOH (Guest)
on 2009-07-12 06:22
(Received via mailing list)
Hi,

2009/7/3 Muhammad Ali <redmine@ruby-lang.org>:
> Thread.current[:x] = 1
>
> Fiber.new{Thread.current[:x]}.resume # => nil
>
> # returns nil when it should return 1
> # even though Thread.current returns the same object


I've heard that this is intentional.  Thread.current is both
thread-local and fiber-local storage.

I can't really remember the rationale, but I think that most of
legacy libraries that uses thread-local storage will expect the
storage to be also fiber-local.
Posted by Muhammad Ali (oldmoe)
on 2009-07-13 12:52
(Received via mailing list)
That makes sense, but I had a need to share data across fibers running 
in
the same thread, shouldn't there be a way to get hold to the parent 
thread's
local storage?

oldmoe
Posted by Roger Pack (Guest)
on 2009-07-13 13:37
(Received via mailing list)
> That makes sense, but I had a need to share data across fibers running in
> the same thread, shouldn't there be a way to get hold to the parent thread's
> local storage?

I agree.
=r
Posted by Yehuda Katz (Guest)
on 2009-07-18 07:22
(Received via mailing list)
Issue #1717 has been updated by Yehuda Katz.


You could do:

  t = Thread.new(Thread.current) do |parent|
    # access to parent
  end

It seems that having fibers have their own Thread.local is a good thing; 
otherwise, people who store local things inside of Thread-local 
variables could have their details suddenly swapped out in certain 
circumstances.

You could even do:

  class Thread
    def self.inherit
      parent = Thread.current
      new do
        parent.keys.each do |key|
          next if key =~ /^__/
          Thread.current[key] = parent[key]
        end
        yield
      end
    end
  end

Which would be used like Thread.new, but automatically copy the parent's 
thread-locals to the new thread.
----------------------------------------
http://redmine.ruby-lang.org/issues/show/1717
Posted by Roger Pack (Guest)
on 2009-07-18 13:24
(Received via mailing list)
>        yield
>      end
>    end
>  end
>
> Which would be used like Thread.new, but automatically copy the parent's thread-locals to the new thread.


It would seem that something like that is probably necessary to
preserve sanity among thread's and fibers.

Another option would be to allow for Fiber#[] to work.

That would be less surprising to me than having Thread.current[]
magically be assigning to two different places, depending on context.
But they'd both require some shenanigens, as if you wanted to allow
library users to write "blind" code you'd have to remap
Thread.current[] to use Fiber.current[] when called within a running
fiber.  Still more code to write but seems more explicit to me and
less surprising.
Just thinking out loud.
=r
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.