Module: Tailwindcss::ProcessRunner
- Defined in:
- lib/tailwindcss/process_runner.rb
Overview
Runs a child process and forwards stop signals (INT/TERM) to it, blocking until it exits, so a process manager that signals this process directly (e.g. foreman) doesn’t leave the child orphaned. Shaped like Process.spawn/+Kernel#system+: it takes an env hash followed by the command.
Constant Summary collapse
- FORWARDED_SIGNALS =
Signals we forward to the spawned process so it shuts down with us instead of being orphaned.
%w[INT TERM].freeze
Class Method Summary collapse
-
.spawn_and_wait(env, *command) ⇒ Object
Spawn
commandwithenvand block until it exits, forwarding INT (Ctrl-C) and TERM (e.g. foreman shutdown) to it so a process manager that signals us directly doesn’t leave an orphaned child behind.
Class Method Details
.spawn_and_wait(env, *command) ⇒ Object
Spawn command with env and block until it exits, forwarding INT (Ctrl-C) and TERM (e.g. foreman shutdown) to it so a process manager that signals us directly doesn’t leave an orphaned child behind. Restores the previous signal handlers before returning so the process-global traps aren’t left changed. Returns the name of the signal that was received (e.g. “TERM”), or nil if the child exited on its own.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/tailwindcss/process_runner.rb', line 19 def spawn_and_wait(env, *command) pid = nil received_signal = nil previous_traps = {} forward_signal = ->(signal) do if pid Process.kill(signal, pid) end rescue Errno::ESRCH # the child already exited end # Trap immediately before spawning. If a signal lands before pid is # assigned, remember it and forward it once the child exists. FORWARDED_SIGNALS.each do |signal| previous_traps[signal] = trap(signal) do received_signal ||= signal forward_signal.call(signal) end end pid = Process.spawn(env, *command) # If a signal arrived during spawn (before pid was set), the handler # couldn't forward it yet, so forward it now. if received_signal forward_signal.call(received_signal) end Process.wait(pid) # Drop the pid so a late signal can't kill a process that reused it. pid = nil received_signal ensure previous_traps.each do |signal, previous_trap| trap(signal, previous_trap) end end |