-
-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document lack of thread safety #11
Conversation
global `ENV` variable. This means that this gem should be avoided in a | ||
multi-threaded environment. | ||
|
||
Internally, this gem mitigates the thread-safety issue by locking a mutex while |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the addition of a mutex, Climate Control is thread safe, but not reentrant. The mutex means only one thread will enter the code at once. This may affect performance, but will not cause bugs. I don't believe it should be avoided in a multi-threaded environment. |
@jferris You are correct that only one thread will enter the Climate Control code at once. But since Climate Control doesn't own the global Hopefully these examples will illustrate the problems: Example 1This example shows that even if Climate Control were thread-safe, it's modification of global state could cause conflicts in other threads in an application. require 'climate_control'
Thread.new do
ClimateControl.modify('PATH' => '/custom/path/for/block') do
sleep 1
end
end
sleep 0.5
puts ENV['PATH'] # => /custom/path/for/block
puts `echo hello world` # raises No such file or directory - echo (Errno::ENOENT) At the very least, the README should contain a warning like:
Example 2This example produces a race condition that causes an environment variable to be deleted. This shows that Climate Control is not thread-safe. Race conditions are notoriously difficult to reproduce, so I monkey patched in a sleep statement that ensures that the race condition is hit every time. require 'climate_control'
# Add a delay to the method in order to consistently reproduce the race condition
ClimateControl::Modifier::OverlappingKeysWithChangedValues.class_eval do
def keys_with_delay
keys_without_delay.tap { sleep 1 }
end
alias_method :keys_without_delay, :keys
alias_method :keys, :keys_with_delay
end
Thread.new do
ClimateControl.modify('FOO' => 'temporary') do
end
end
sleep 0.5
ENV['FOO'] = 'b'
puts ENV['FOO'].inspect # => "b"
sleep 1
puts ENV['FOO'].inspect # => nil |
Also, the lazy initialization of |
@balexand thanks for the detailed response.
That's true; since we don't own
Good catch. Could you open an issue for that one? Code Climate should at least be thread-safe when using its public API, so I think that's a bug. |
I'll make one more argument for why this gem should be documented as being not thread-safe. Then I'll leave it up to the maintainers of the gem to decide how to word the thread-safety warning. @jferris wrote in the previous comment:
If This is what I'm describing in the README when I write that this gem is
|
I think this has been addressed now as of #24? LMK and we can re-open if it's still a concern. |
I think so yeah. I'm going to close this and we can re-open it if someone finds that not to be the case. |
It is important to document the thread-safety limitations of this gem. Doing so could avoid serious bugs in other gems like thoughtbot/paperclip#1709. Thanks!