> ## Documentation Index
> Fetch the complete documentation index at: https://tally.wharflab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# tally/no-ungraceful-stopsignal

> STOPSIGNAL should not use signals that prevent graceful shutdown.

STOPSIGNAL should not use signals that prevent graceful shutdown.

| Property | Value                                     |
| -------- | ----------------------------------------- |
| Severity | Warning                                   |
| Category | Correctness                               |
| Default  | Enabled                                   |
| Auto-fix | Yes (suggestion, requires `--fix-unsafe`) |

## Description

`STOPSIGNAL` tells the container runtime which signal to send when stopping the
container. Using `SIGKILL` or `SIGSTOP` defeats the purpose of `STOPSIGNAL`:

* **SIGKILL** (signal 9) cannot be caught, blocked, or ignored. The process is
  terminated immediately with no opportunity to flush data, close connections, or
  perform any cleanup. The container runtime will send SIGKILL automatically after
  the stop timeout anyway, so setting it as the STOPSIGNAL skips the graceful
  shutdown window entirely.

* **SIGSTOP** (signal 19) suspends the process instead of terminating it. The
  container will not exit, and the runtime will eventually escalate to SIGKILL
  after the stop timeout.

This rule also detects non-canonical forms such as numeric signal values (`9`, `19`),
signals without the `SIG` prefix (`KILL`, `STOP`), and lowercase variants (`sigkill`).

Environment variable references (e.g. `STOPSIGNAL $MY_SIGNAL`) are skipped because
the signal value cannot be determined statically.

Windows stages are skipped because `STOPSIGNAL` has no effect on Windows
containers — POSIX signals are not delivered to Windows processes.

## References

* [Dockerfile reference -- STOPSIGNAL](https://docs.docker.com/reference/dockerfile/#stopsignal)
* [signal(7) -- Linux manual page](https://man7.org/linux/man-pages/man7/signal.7.html)

## Examples

### Bad

```dockerfile theme={null}
FROM alpine:3.20
# SIGKILL prevents graceful shutdown
STOPSIGNAL SIGKILL
CMD ["/app"]
```

```dockerfile theme={null}
FROM postgres:16
# Numeric 9 is SIGKILL
STOPSIGNAL 9
CMD ["postgres"]
```

```dockerfile theme={null}
FROM nginx:1.27
# SIGSTOP suspends instead of stopping
STOPSIGNAL SIGSTOP
CMD ["nginx", "-g", "daemon off;"]
```

### Good

```dockerfile theme={null}
FROM alpine:3.20
# SIGTERM allows graceful shutdown (default)
STOPSIGNAL SIGTERM
CMD ["/app"]
```

```dockerfile theme={null}
FROM nginx:1.27
# SIGQUIT triggers graceful shutdown for nginx
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
```

```dockerfile theme={null}
FROM postgres:16
# SIGINT triggers fast shutdown for PostgreSQL
STOPSIGNAL SIGINT
CMD ["postgres"]
```

## Auto-fix

The suggested fix replaces the ungraceful signal with `SIGTERM`, which is the
standard graceful stop signal for most processes:

```bash theme={null}
tally lint --fix --fix-unsafe Dockerfile
```

The fix uses `FixSuggestion` safety because replacing the signal changes container
stop behavior. Review the replacement to ensure `SIGTERM` is appropriate for your
daemon. Some daemons prefer different signals for graceful shutdown (e.g. `SIGQUIT`
for nginx, `SIGINT` for PostgreSQL).

## Configuration

```toml theme={null}
[rules.tally.no-ungraceful-stopsignal]
severity = "warning"  # Options: "off", "error", "warning", "info", "style"
```
