Class: HotCell::Supervisor
- Inherits:
-
Object
- Object
- HotCell::Supervisor
- Defined in:
- lib/hot_cell/supervisor.rb
Overview
Accepts, queues, dispatches, times, kills, reaps, and cleans up. It never evaluates image data.
That last rule is mechanical rather than defensive: libvips starts its thread pool on the first evaluation and that pool does not survive fork, so a supervisor that has touched an image forks workers that deadlock forever. Reading a request line would be harmless — it is a control message from the trusted side on a bounded buffer — but the supervisor does not need to, and staying out of the request is what lets it dispatch a connection whose descriptors are still queued on it.
Dispatching rather than letting workers accept is what makes the rest work. The supervisor needs to own
the accept anyway, for the queue, for queued_ms, and to answer capacity. It also means the supervisor
knows when every worker started its current request, which is what the deadline needs.
Defined Under Namespace
Constant Summary collapse
- SUN_PATH_MAX =
A path longer than this fails to bind with an error that does not say so. Darwin allows four fewer bytes than Linux, and control.sock is the longer of the two names, so it overflows first.
RUBY_PLATFORM.include?("darwin") ? 104 : 108
- SOCKETS =
[ "work.sock", "control.sock" ].freeze
- PTRACE_SCOPE =
Request memory is protected by kernel.yama.ptrace_scope >= 1, and nothing else protects it. That is a host sysctl no container flag can supply.
"/proc/sys/kernel/yama/ptrace_scope"- CONTROL_BACKLOG =
Only to bound the list. The channel's whole value is answering when nothing else does, so this is set far above any real scrape rate rather than as a throttle.
64
Instance Attribute Summary collapse
-
#configuration ⇒ Object
readonly
Returns the value of attribute configuration.
-
#counters ⇒ Object
readonly
Returns the value of attribute counters.
-
#directory ⇒ Object
readonly
Returns the value of attribute directory.
-
#log ⇒ Object
readonly
Returns the value of attribute log.
-
#workspace ⇒ Object
readonly
Returns the value of attribute workspace.
Instance Method Summary collapse
- #boot ⇒ Object
-
#initialize(directory:, workspace: nil, configuration: HotCell.configuration, log: Log.new, ptrace_scope_path: PTRACE_SCOPE) ⇒ Supervisor
constructor
A new instance of Supervisor.
- #run ⇒ Object
Constructor Details
#initialize(directory:, workspace: nil, configuration: HotCell.configuration, log: Log.new, ptrace_scope_path: PTRACE_SCOPE) ⇒ Supervisor
Returns a new instance of Supervisor.
110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/hot_cell/supervisor.rb', line 110 def initialize(directory:, workspace: nil, configuration: HotCell.configuration, log: Log.new, ptrace_scope_path: PTRACE_SCOPE) @directory = directory @workspace = workspace || File.join(Dir.tmpdir, "hotcell-workspace") @configuration = configuration @log = log @ptrace_scope_path = ptrace_scope_path @children = {} @queue = [] @control_pending = [] @counters = Counters.new @stopping = false end |
Instance Attribute Details
#configuration ⇒ Object (readonly)
Returns the value of attribute configuration.
108 109 110 |
# File 'lib/hot_cell/supervisor.rb', line 108 def configuration @configuration end |
#counters ⇒ Object (readonly)
Returns the value of attribute counters.
108 109 110 |
# File 'lib/hot_cell/supervisor.rb', line 108 def counters @counters end |
#directory ⇒ Object (readonly)
Returns the value of attribute directory.
108 109 110 |
# File 'lib/hot_cell/supervisor.rb', line 108 def directory @directory end |
#log ⇒ Object (readonly)
Returns the value of attribute log.
108 109 110 |
# File 'lib/hot_cell/supervisor.rb', line 108 def log @log end |
#workspace ⇒ Object (readonly)
Returns the value of attribute workspace.
108 109 110 |
# File 'lib/hot_cell/supervisor.rb', line 108 def workspace @workspace end |
Instance Method Details
#boot ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/hot_cell/supervisor.rb', line 124 def boot verify_socket_paths! verify_limits! verify_ptrace_scope! prepare_directories preload @work = listen "work.sock" @control = listen "control.sock" @control_handler = Control.new(configuration: configuration, counters: counters) trap_signals log.write "cell.boot", pid: Process.pid, directory: directory, operations: Registry.names, configuration: configuration.to_h self end |
#run ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/hot_cell/supervisor.rb', line 140 def run until stopped? readable, = IO.select(sources, nil, nil, wait_for) Array(readable).each { |source| handle source } enforce_deadlines enforce_retirements expire_queue expire_control retire_idle if @stopping pump end ensure shutdown end |