Bug #14353
closed$SAFE should stay at least thread-local for compatibility
Description
In #14250 $SAFE changed from a frame+thread-local variable to a process-wide global variable.
This feels wrong and breaks the most common usage of $SAFE in tests:
Thread.new {
$SAFE = 1
sth that should be checked to work under $SAFE==1
}.join
It is very clear this is incompatible given how many files (33!) had to be changed in r61510.
And it has wide ranging confusing side-effects, one example: https://travis-ci.org/ruby/spec/jobs/328524568
I agree frame-local is too much for $SAFE.
But removing thread-local seems to only introduce large incompatibilities.
It also makes it impossible to use it in a thread-safe way.
The common pattern (not necessarily for $SAFE, more often for $VERBOSE):
begin
old = $SAFE
$SAFE = 1
something under SAFE==1
ensure
$SAFE = old
end
is unsafe if two threads run it concurrently (The last thread executing $SAFE = old
might restore to 1 even though it should be 0).
(Actually I believe most built-in variables (e.g. $VERBOSE) should be thread-local and not process-wide due to this)
Since $SAFE is being deprecated and removed, I don't see any reason to make it more incompatible than needed.
@ko1 (Koichi Sasada) Can we switch it back to thread-local for compatibility, avoiding headaches and keeping it usable with multiple threads?