A renderer is force-killed at the end of every stop window — how do you tell a signal never delivered from one that was ignored?
answer
- the symptom is identical either way
- look for a first line, not a last
- ask what is at position one
- instrument the handler's entry
- reproduce and signal it by hand
basics
~20 sLook for evidence that the application itself acted. The first line of its own shutdown path proves delivery; no such line, plus a first process that is a wrapper forwarding nothing or an application with no handler installed, points at a request that never arrived.
solid answer
~50 sThe two causes produce an identical symptom — work cut off at the end of the window — and have opposite fixes, so guessing costs you a release. Three branches are worth separating. If the application logged the first line of its shutdown path, the request was **delivered** and the remaining question is duration, not delivery. If the application holds position one with no handler installed, the request was delivered and discarded: at position one an unhandled termination signal is commonly not fatal, so the process simply carries on. If the first process is a wrapper that forwards nothing, the request **never reached** the application at all. The cheap decisive test is to reproduce it: start the same image, send a stop request by hand, and watch. Instrument the handler's entry, not its exit, so the evidence survives a kill.
code
pseudocode · 11 lines# deciding between "never delivered" and "delivered and ignored"
if shutdown_handler_logged_its_first_line:
verdict = "delivered" # remaining question is duration
else if first_process is the_application:
verdict = "delivered, no handler installed"
else: # first process is a wrapper
if wrapper forwards stop_request to its children:
verdict = "delivered; check the handler and the log flush"
else:
verdict = "never delivered"go deeper
The takeaway to carry is that a stop ending in a forced kill has two very different causes, and telling them apart starts with asking what process the request was actually delivered to.
Be able to name the three branches and their evidence: a shutdown line means delivered, a non-forwarding wrapper at position one means never delivered, an application there with no handler means delivered and discarded.
Demonstrate the diagnostic discipline: instrument the entry to the handler rather than its exit, read stop duration as a signal, and reproduce with a manual stop request rather than arguing from a dashboard.
Frame it as an observability gap rather than an incident. Decide what every image must emit so that delivery is never in question again, and who pays for that being uniform across teams.
## Two causes wearing the same symptom From outside, a stop that ends in a forced kill looks the same whatever the cause: the window elapses, the process disappears, work is lost. Underneath there are two distinct failures, and their fixes point in opposite directions. **Never delivered** means nothing in the container ever learned that a stop was requested; the fix is at position one, in forwarding or in installing a handler. **Delivered and not completed** means the application heard the request and did not finish in time; the fix is in the shutdown path or in the window it is given. Apply the second fix to the first problem and you have made every stop slower and changed nothing else — which is the single most common wasted week in this material. ## The evidence that separates them Three questions, in this order, put you in a branch: 1. **Did the application's own shutdown path produce any output?** One line at the *entry* to the handler is proof of delivery. The absence of a *final* line proves nothing, because a forced kill leaves no trace from inside the process and unflushed output can be lost with it. This is why you instrument the first line and not the last. 2. **What is actually at position one?** If it is a wrapper, read it and answer one question: does it forward to its children, or does it only wait for them? A wrapper that only waits is the never-delivered case, with no further investigation required. 3. **If the application is at position one, does it install a handler?** At that position an unhandled termination signal is commonly discarded rather than ending the process, so an application that would die from it anywhere else keeps running here. That is delivered-and-discarded: the request arrived and nothing was listening. There are two secondary tells worth knowing: - **Timing.** A container that always uses the whole window, to the second, on every stop, is behaving like something that is not reacting at all. A container whose stop duration varies with how much work was in flight is reacting. - **A prompt exit is not proof.** A wrapper that reacts to the signal by exiting, without forwarding it, ends the container immediately — because the container ends when its first process ends — while the renderer is cut off mid-write. Fast and clean look alike from outside and are opposites. ## Making the next incident cheap Most of the difficulty here is that nobody instrumented delivery before the incident. Three cheap habits remove the ambiguity permanently: - log one line on **entry** to the shutdown handler, before any work is done, and flush it; - log one line from the first process when it **forwards** a request onward, if it is a wrapper or an init you wrote; - record the **duration** of each stop, so a flat line at exactly the window length is visible without anyone reading logs. With those three, the branch is decided by reading two log lines instead of by argument. ## The reproduction that settles it When the evidence is missing, reproduce rather than reason. Start the same image outside the serving path, let it reach its normal working state, send a stop request to the container by hand, and watch the output as it happens. You are looking for exactly two facts: whether any shutdown line appears, and whether the process ends before the window would have expired. A container that ends promptly with a shutdown line is healthy. One that ends promptly with no shutdown line is the wrapper that exits without forwarding. One that runs the whole window with no shutdown line is the wrapper that swallows, or the application with no handler. ## Why the branches must not be merged | Branch | Evidence | Fix | What the other fix would do | |---|---|---|---| | Never delivered | No shutdown line; first process is a wrapper that only waits | Forward from position one, or put the application there | A longer window makes every stop slower, changes nothing else | | Delivered, no handler | No shutdown line; application is at position one | Install a handler for the termination signal | Replacing position one changes nothing; it was already right | | Delivered, did not finish | Shutdown line present; stop duration varies with work in flight | Shorten the shutdown path, or revisit the window | Adding an init at position one changes nothing at all | The third row is where this subject hands off: once delivery is proven, what the application should do with its remaining time is a different question with a different owner.
- The handler logs its first line and the process is still killed at the end of the window. Whose problem is that now?Not this one. Delivery is proven, so the question becomes how long the shutdown path takes and how long the window allows — a different subject with different levers, such as refusing new work earlier or sizing the window against the longest unit of work. The value of the evidence is that it closes the delivery argument for good.
- Why is the absence of a final shutdown log line weak evidence?Because a forced kill leaves no trace from inside the process and can take buffered output with it. A handler that ran and was halfway through can look exactly like one that never ran. Logging on entry to the handler, and flushing that line, is what makes the evidence survive the kill.
- The container exits promptly on a stop request but in-flight renders are still lost. Does that prove forwarding works?No. It proves that the first process ended, which is what ends a container. A wrapper that handles the signal by exiting without forwarding gives you exactly that: a fast, tidy-looking stop with the renderer cut off mid-write. Check for the application's own shutdown line, not for a quick exit.
saying these in an interview costs you the question
- Concludes the application ignored the signal because it did not exit
- Lengthens the grace window before checking delivery at all
- Treats a missing final log line as proof the handler never ran
- Reads a prompt container exit as proof the child was told
- Thinks the forced kill can be observed or logged from inside the process