Deadlock race when calling ScheduledTask#reschedule
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 35/100
Direzione di ricerca
Start with lib/concurrent-ruby/concurrent/scheduled_task.rb, especially reschedule, ns_reschedule, and schedule_time, then inspect lib/concurrent-ruby/concurrent/executor/timer_set.rb and its process_tasks and remove_task paths. Reproduce the lock-ordering race described in the issue and use the cited priority queue stack to observe it. Done means the reschedule and timer-processing paths no longer deadlock.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
I believe I've found a deadlock in ScheduledTask / TimerSet, which appears to be present in both old (1.2.3) and current (1.3.6) concurrent-ruby.
If one creates a ScheduledTask, and calls reschedule() on it from the main thread on it right as the TimerSet background thread wakes up to run the #process_tasks loop, a deadlock can occur.
Thread 1: ScheduledTask#reschedule is called explicitly:
- locks ScheduledTask.synchronize (scheduled_task.rb:265)
- calls ns_reschedule, which in turn calls
TimerSet#remove_task - which tries to lock TimerSet.synchronize (timer_set.rb:117)
Thread 2: TimerSet#process_tasks runs auto in the background:
- Calls
task = synchronize { @queue.pop }(timer_set.rb:167) - This locks TImerSet.synchronize
- @queue.pop tries to pop the soonest work item, which results in invoking
ScheduledTask#schedule_timeto sort/compare queue items - which tries to lock ScheduledTask.synchronize before accessing @time (scheduled_task.rb:207)
Below I show two threads which are deadlocked in this fashion, showing the issue, and where each thread grabs each lock. One thread is a puma request thread, which ends up calling ScheduledTask#reschedule.
# put_metric_data request #2 (TID-dh2ik puma srv tp 005)
#
# Lock Conditions:
# - TimerSet: trying to lock
# - ScheduledTask: locked
#
[171733] Thread: TID-dh2ik puma srv tp 005
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'synchronize'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'synchronize'
#### <---- TRY TO LOCK TimerSet.synchronize ####
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/timer_set.rb:116:in 'remove_task'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/scheduled_task.rb:328:in 'ns_reschedule'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/scheduled_task.rb:265:in 'block in reschedule'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:46:in 'synchronize'
#### <---- LOCK ScheduledTask.synchronize ####
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/scheduled_task.rb:265:in 'reschedule'
# SNIP, long puma/rails request backtrace which doesn't use concurrent
# concurrent-ruby scheduled_task (TID-4jpio worker-1)
#
# Lock Conditions:
# - TimerSet: locked
# - ScheduledTask: trying to lock
#
[171733] Thread: TID-4jpio worker-1
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'synchronize'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'synchronize'
#### <---- TRY TO LOCK ScheduledTask.synchronize ####
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/scheduled_task.rb:207:in 'schedule_time'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/scheduled_task.rb:214:in '<=>'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb:120:in 'ordered?'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb:133:in 'sink'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb:70:in 'pop'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/timer_set.rb:164:in 'block (2 levels) in process_tasks'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'block in synchronize'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'synchronize'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb:48:in 'synchronize'
#### <---- LOCK TimerSet.synchronize ####
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/timer_set.rb:164:in 'block in process_tasks'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/timer_set.rb:144:in 'loop'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/timer_set.rb:144:in 'process_tasks'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:359:in 'run_task'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:350:in 'block (3 levels) in create_worker'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:341:in 'loop'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:341:in 'block (2 levels) in create_worker'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:340:in 'catch'
concurrent-ruby-1.2.3/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb:340:in 'block in create_worker'
- Lingua principale
- Ruby
- Stelle
- 5.8k
- Fork
- 420
- Merge medio
- 20h 45m
- PR unite (30g)
- 4
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di ruby-concurrency/concurrent-ruby
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
ruby-concurrency/concurrent-ruby#1118 ·
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
ruby-concurrency/concurrent-ruby#1095 · 8 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
ruby-concurrency/concurrent-ruby#1093 · 3 commenti ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 45/100
ruby-concurrency/concurrent-ruby#1091 ·
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 35/100
ruby-concurrency/concurrent-ruby#1072 · 1 reazione ·
Tutte le issue di ruby-concurrency/concurrent-ruby
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 90/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
-
バグ
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 92/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
Version bump for OpenVox 9 Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
voxpupuli/puppet-epel#186 · 1 commento ·