diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-15 15:07:44 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-03-15 15:07:44 +0300 |
commit | 6a9ab27963fc1479fe7c78581b942c8dcce322e5 (patch) | |
tree | 8d32f4f66efde1b426658a74d0276e5250091ab7 /lib/gitlab/process_supervisor.rb | |
parent | 389d5aa505a916b0506b7b73dcc3be342d724976 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab/process_supervisor.rb')
-rw-r--r-- | lib/gitlab/process_supervisor.rb | 61 |
1 files changed, 50 insertions, 11 deletions
diff --git a/lib/gitlab/process_supervisor.rb b/lib/gitlab/process_supervisor.rb index f0d2bbc33bd..18fd24aa582 100644 --- a/lib/gitlab/process_supervisor.rb +++ b/lib/gitlab/process_supervisor.rb @@ -9,7 +9,7 @@ module Gitlab # The supervisor will also trap termination signals if provided and # propagate those to the supervised processes. Any supervised processes # that do not terminate within a specified grace period will be killed. - class ProcessSupervisor + class ProcessSupervisor < Gitlab::Daemon DEFAULT_HEALTH_CHECK_INTERVAL_SECONDS = 5 DEFAULT_TERMINATE_INTERVAL_SECONDS = 1 DEFAULT_TERMINATE_TIMEOUT_SECONDS = 10 @@ -21,13 +21,18 @@ module Gitlab check_terminate_interval_seconds: DEFAULT_TERMINATE_INTERVAL_SECONDS, terminate_timeout_seconds: DEFAULT_TERMINATE_TIMEOUT_SECONDS, term_signals: %i(INT TERM), - forwarded_signals: []) + forwarded_signals: [], + **options) + super(**options) @term_signals = term_signals @forwarded_signals = forwarded_signals @health_check_interval_seconds = health_check_interval_seconds @check_terminate_interval_seconds = check_terminate_interval_seconds @terminate_timeout_seconds = terminate_timeout_seconds + + @pids = [] + @alive = false end # Starts a supervision loop for the given process ID(s). @@ -39,32 +44,66 @@ module Gitlab # start observing those processes instead. Otherwise it will shut down. def supervise(pid_or_pids, &on_process_death) @pids = Array(pid_or_pids) + @on_process_death = on_process_death trap_signals! + start + end + + # Shuts down the supervisor and all supervised processes with the given signal. + def shutdown(signal = :TERM) + return unless @alive + + stop_processes(signal) + stop + end + + def supervised_pids + @pids + end + + private + + def start_working @alive = true + end + + def stop_working + @alive = false + end + + def run_thread while @alive sleep(@health_check_interval_seconds) - check_process_health(&on_process_death) + check_process_health end end - private - - def check_process_health(&on_process_death) + def check_process_health unless all_alive? - dead_pids = @pids - live_pids - @pids = Array(yield(dead_pids)) + existing_pids = live_pids # Capture this value for the duration of the block. + dead_pids = @pids - existing_pids + new_pids = Array(@on_process_death.call(dead_pids)) + @pids = existing_pids + new_pids @alive = @pids.any? end end + def stop_processes(signal) + # Set this prior to shutting down so that shutdown hooks which read `alive` + # know the supervisor is about to shut down. + @alive = false + + # Shut down supervised processes. + signal_all(signal) + wait_for_termination + end + def trap_signals! ProcessManagement.trap_signals(@term_signals) do |signal| - @alive = false - signal_all(signal) - wait_for_termination + stop_processes(signal) end ProcessManagement.trap_signals(@forwarded_signals) do |signal| |