Skip to content

Commit eb81fff

Browse files
committed
avoid "can't be called from trap context" errors in ThreadLocalVar
1 parent b8ec2e3 commit eb81fff

File tree

1 file changed

+20
-16
lines changed

1 file changed

+20
-16
lines changed

lib/concurrent/atomic/ruby_thread_local_var.rb

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ class RubyThreadLocalVar < AbstractThreadLocalVar
2929
# array, so we don't leak memory
3030

3131
# @!visibility private
32-
FREE = []
33-
LOCK = Mutex.new
32+
FREE = []
33+
LOCK = Mutex.new
3434
ARRAYS = {} # used as a hash set
3535
@@next = 0
3636
private_constant :FREE, :LOCK, :ARRAYS
@@ -72,9 +72,9 @@ def value=(value)
7272
def allocate_storage
7373
@index = LOCK.synchronize do
7474
FREE.pop || begin
75-
result = @@next
76-
@@next += 1
77-
result
75+
result = @@next
76+
@@next += 1
77+
result
7878
end
7979
end
8080
ObjectSpace.define_finalizer(self, self.class.threadlocal_finalizer(@index))
@@ -83,13 +83,15 @@ def allocate_storage
8383
# @!visibility private
8484
def self.threadlocal_finalizer(index)
8585
proc do
86-
LOCK.synchronize do
87-
FREE.push(index)
88-
# The cost of GC'ing a TLV is linear in the number of threads using TLVs
89-
# But that is natural! More threads means more storage is used per TLV
90-
# So naturally more CPU time is required to free more storage
91-
ARRAYS.each_value do |array|
92-
array[index] = nil
86+
Thread.new do # avoid error: can't be called from trap context
87+
LOCK.synchronize do
88+
FREE.push(index)
89+
# The cost of GC'ing a TLV is linear in the number of threads using TLVs
90+
# But that is natural! More threads means more storage is used per TLV
91+
# So naturally more CPU time is required to free more storage
92+
ARRAYS.each_value do |array|
93+
array[index] = nil
94+
end
9395
end
9496
end
9597
end
@@ -98,10 +100,12 @@ def self.threadlocal_finalizer(index)
98100
# @!visibility private
99101
def self.thread_finalizer(array)
100102
proc do
101-
LOCK.synchronize do
102-
# The thread which used this thread-local array is now gone
103-
# So don't hold onto a reference to the array (thus blocking GC)
104-
ARRAYS.delete(array.object_id)
103+
Thread.new do # avoid error: can't be called from trap context
104+
LOCK.synchronize do
105+
# The thread which used this thread-local array is now gone
106+
# So don't hold onto a reference to the array (thus blocking GC)
107+
ARRAYS.delete(array.object_id)
108+
end
105109
end
106110
end
107111
end

0 commit comments

Comments
 (0)