diff options
author | yuuji.yaginuma <yuuji.yaginuma@gmail.com> | 2017-08-27 21:31:48 +0900 |
---|---|---|
committer | yuuji.yaginuma <yuuji.yaginuma@gmail.com> | 2017-08-28 21:48:05 +0900 |
commit | 8536ebeefad411ffd1b476c6b499aaec84efea80 (patch) | |
tree | 1a1f7d8da95b95df36d914df4139961e8ee8505d | |
parent | ca2a66abef16f0b0a529c1cd533e7ba179e30890 (diff) | |
download | rails-8536ebeefad411ffd1b476c6b499aaec84efea80.tar.gz rails-8536ebeefad411ffd1b476c6b499aaec84efea80.tar.bz2 rails-8536ebeefad411ffd1b476c6b499aaec84efea80.zip |
Fix `can't modify frozen String` error in `DebugLocks`
Without this, `DebugLocks` middleware raises an error as follwing:
```
Puma caught this error: can't modify frozen String (RuntimeError)
actionpack/lib/action_dispatch/middleware/debug_locks.rb:97:in `block in render_details'
actionpack/lib/action_dispatch/middleware/debug_locks.rb:64:in `each'
actionpack/lib/action_dispatch/middleware/debug_locks.rb:64:in `map'
actionpack/lib/action_dispatch/middleware/debug_locks.rb:64:in `render_details'
actionpack/lib/action_dispatch/middleware/debug_locks.rb:37:in `call'
railties/lib/rails/engine.rb:524:in `call'
```
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/debug_locks.rb | 8 | ||||
-rw-r--r-- | actionpack/test/dispatch/debug_locks_test.rb | 38 |
2 files changed, 42 insertions, 4 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/debug_locks.rb b/actionpack/lib/action_dispatch/middleware/debug_locks.rb index c61a941010..541fb25b6c 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_locks.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_locks.rb @@ -63,19 +63,19 @@ module ActionDispatch str = threads.map do |thread, info| if info[:exclusive] - lock_state = "Exclusive" + lock_state = "Exclusive".dup elsif info[:sharing] > 0 - lock_state = "Sharing" + lock_state = "Sharing".dup lock_state << " x#{info[:sharing]}" if info[:sharing] > 1 else - lock_state = "No lock" + lock_state = "No lock".dup end if info[:waiting] lock_state << " (yielded share)" end - msg = "Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n" + msg = "Thread #{info[:index]} [0x#{thread.__id__.to_s(16)} #{thread.status || 'dead'}] #{lock_state}\n".dup if info[:sleeper] msg << " Waiting in #{info[:sleeper]}" diff --git a/actionpack/test/dispatch/debug_locks_test.rb b/actionpack/test/dispatch/debug_locks_test.rb new file mode 100644 index 0000000000..d69614bd79 --- /dev/null +++ b/actionpack/test/dispatch/debug_locks_test.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require "abstract_unit" + +class DebugLocksTest < ActionDispatch::IntegrationTest + setup do + build_app + end + + def test_render_threads_status + thread_ready = Concurrent::CountDownLatch.new + test_terminated = Concurrent::CountDownLatch.new + + thread = Thread.new do + ActiveSupport::Dependencies.interlock.running do + thread_ready.count_down + test_terminated.wait + end + end + + thread_ready.wait + + get "/rails/locks" + + test_terminated.count_down + + assert_match(/Thread.*?Sharing/, @response.body) + ensure + thread.join + end + + private + def build_app + @app = self.class.build_app do |middleware| + middleware.use ActionDispatch::DebugLocks + end + end +end |