Skip to content

Commit 7b2e8d8

Browse files
rosaclaude
andcommitted
Clean up dead thread from process_instances when replacing it
When a thread dies, `replace_thread` deleted its entry from `configured_processes` but not from `process_instances`. On the next supervise loop, `check_and_replace_terminated_processes` would find the same dead thread again, call `replace_thread`, and `configured_processes.delete(thread_id)` would return nil — crashing with `undefined method 'instantiate' for nil`. Mirror the pattern already used in `ForkSupervisor#replace_fork`: delete from `process_instances` first and guard against the entry already being gone. Fixes #710 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5518a4d commit 7b2e8d8

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

lib/solid_queue/async_supervisor.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ def check_and_replace_terminated_processes
2424

2525
def replace_thread(thread_id, instance)
2626
SolidQueue.instrument(:replace_thread, supervisor_pid: ::Process.pid) do |payload|
27-
payload[:thread] = instance
27+
if process_instances.delete(thread_id)
28+
payload[:thread] = instance
2829

29-
error = Processes::ThreadTerminatedError.new(instance.name)
30-
release_claimed_jobs_by(instance, with_error: error)
30+
error = Processes::ThreadTerminatedError.new(instance.name)
31+
release_claimed_jobs_by(instance, with_error: error)
3132

32-
start_process(configured_processes.delete(thread_id))
33+
start_process(configured_processes.delete(thread_id))
34+
end
3335
end
3436
end
3537

0 commit comments

Comments
 (0)