Issue #19333 has been updated by ioquatix (Samuel Williams).
While the proposed idea is a good move in the right direction, it doesn't handle cases
where several (a large number) threads all have the SAME thread local, and that thread
local goes out of scope, e.g.
```
name = ":local-#{object_id}
100.times do
Thread.new do
thing = ... something that consumes memory ...
Thread.current.thread_variable_set(name, thing)
# Thread lives for a long time
while job = jobs.pop
job.call
end
end
end
```
Even when `name` is no longer useful for any purpose, all those threads sill still have
that thread local set. There is no global way to say "For all threads that have a
thread local set for name, please clear it".
In order to do that, we'd need to introduce a `Thread::Local` object which uniquely
identifies an association in 0 or more threads, and when that `Thread::Local` instance is
GCed, all threads which have it set, have it cleared. This ensures that threads don't
leak memory. Consider a work pool that allocates a new `Thread::Local `every now and
then... eventually threads will have lots of locals which are potentially no longer
useful.
That being said, the other option is just not to encourage people to have long running
threads that accumulate cruft over time.
----------------------------------------
Feature #19333: Setting (Fiber Local|Thread Local|Fiber Storage) to nil should delete
value in order to avoid memory leaks.
https://bugs.ruby-lang.org/issues/19333#change-101239
* Author: ioquatix (Samuel Williams)
* Status: Open
* Priority: Normal
----------------------------------------
As it stands, Fiber Locals, Thread Locals and Fiber Storage have no way of deleting
key-value associations.
```ruby
100.times do |i|
name = :"variable-#{i}"
Thread.current[name] = 10
end
```
Because of this, dynamically generated associations can leak over time. This is worse for
things like Threads that might be pooled (or maybe an argument against user-space
pooling).
In any case, having a way to delete those associations would allow application code to at
least delete the associations when they no longer make sense.
I propose that assigning `nil` to "locals" or "storage" should
effectively delete them.
e.g.
```ruby
100.times do |i|
name = :"variable-#{i}"
Thread.current[name] = 10
Thread.current[name] = nil # delete association
end
```
A more invasive alternative would be to define new interfaces like `Thread::Local`,
`Fiber::Local` and `Fiber::Storage::Local` (or something) which correctly clean up on GC.
--
https://bugs.ruby-lang.org/