From: merch-redmine@... Date: 2019-07-17T23:58:25+00:00 Subject: [ruby-core:93826] [Ruby master Bug#8444] Regexp vars $~ and friends are not thread local Issue #8444 has been updated by jeremyevans0 (Jeremy Evans). Backport deleted (1.9.3: UNKNOWN, 2.0.0: UNKNOWN) This behavior is still present in the master branch and it does seem like a bug to me. It does seems specific to returning a closure from a method and having two separate threads call that closure. It doesn't occur if you pass the proc directly to `Thread.new`: ```ruby def get_proc lambda do |str| str =~ /(.+)/ sleep 0.1 puts "got #{$1} from #{str}\n" end end proc = get_proc t1 = Thread.new("abc", &proc) t2 = Thread.new("def", &proc) t1.join t2.join ``` or if you switch to calling a method directly: ```ruby def get_proc str str =~ /(.+)/ sleep 0.1 puts "got #{$1} from #{str}\n" end t1 = Thread.new { get_proc "abc" } t2 = Thread.new { get_proc "def" } t1.join t2.join ``` From some debugging, one difference between the two cases in the original post is that different branches are taken in `lep_svar`, with the failing case taking the `if` and the passing case taking the `else`. ---------------------------------------- Bug #8444: Regexp vars $~ and friends are not thread local https://bugs.ruby-lang.org/issues/8444#change-79693 * Author: jamespharaoh (James Pharaoh) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: trunk * Backport: ---------------------------------------- =begin In the docs for the Regexp special variables, $~ and friends, it says "These global variables are thread-local and method-local variables". However the following gives an unexpected result: def get_proc proc do |str| str =~ /(.+)/ sleep 0.1 puts "got #{$1} from #{str}\n" end end proc = get_proc t1 = Thread.new { proc.call "abc" } t2 = Thread.new { proc.call "def" } t1.join t2.join This outputs the following: got abc from abc got abc from def The expected result is of course: got abc from abc got def from def Clearly the variables are being scoped to the get_proc method and are being shared by both threads. This runs contrary to the documentation and also to expectations. This behaviour should either be changed, or the documentation updated to reflect the actual behaviour. Interestingly, the following does work as expected: proc = proc do |str| str =~ /(.+)/ sleep 0.1 puts "got #{$1} from #{str}\n" end t1 = Thread.new { proc.call "abc" } t2 = Thread.new { proc.call "def" } t1.join t2.join =end -- https://bugs.ruby-lang.org/ Unsubscribe: