SIGSEGV (Signal 11) in Docker & Kubernetes
SIGSEGV is signal 11, raised when the CPU reports a memory fault the kernel cannot resolve. The default action is terminate with a core dump, and the parent observes 139 = 128 + 11. It is a memory-safety signal, not a memory-limit signal; OOM kills use SIGKILL and 137.
Proof commands: confirm the exit status and the killer
Run these before changing anything. The first two identify what the runtime recorded; the third finds a kernel-level kill on the host. Replace the placeholder container ID, pod name or host path with your own.
Docker inspect
docker inspect <container_id> --format '{{.State.Status}} | ExitCode: {{.State.ExitCode}} | OOMKilled: {{.State.OOMKilled}}'Kubernetes state
kubectl get pod <pod_name> -o jsonpath='{range .status.containerStatuses[*]}{.name}{"\t"}{.lastState.terminated.reason}{"\tExit:"}{.lastState.terminated.exitCode}{"\n"}{end}'Kernel fault and core
sudo dmesg -T | grep -E -i 'segfault|general protection|traps'; coredumpctl list | tail -n 10The kernel's segfault line names the process and gives the fault address and trap code. A core file gives the backtrace. If both are absent, enable core capture or attach a debugger; retrying the same image without symbols will only reproduce the same 139.
Three production root causes
Default action: terminate with a core dump. It is a memory fault in native code, a cgo boundary, a JIT or a libc/architecture mismatch. Get a core dump or the runtime crash log and reproduce with symbols; increasing memory will not fix it.
1. A memory-safety defect in native code
C and C++ extensions, Rust unsafe blocks, cgo and JIT-generated code can read or write an invalid address. The crash may occur under load or only with one input. Run the workload under ASan or analyze the core with gdb and the matching debug symbols.
2. A libc or C++ ABI mismatch
A binary built against glibc loaded into a musl image, or a native module built against a different libstdc++, can fault on startup. The same artifact may work on the build host and fail in production. Build native dependencies inside the runtime image and pin the toolchain.
3. Stack exhaustion or a VM/JIT crash
Deep recursion or a thread with a small stack can fault instead of raising a clean exception. The JVM writes hs_err_pid*.log on a native crash; Go prints a goroutine traceback on a fatal signal by default, and GOTRACEBACK=crash additionally aborts with a core dump. Capture the report before changing limits, because a larger stack can mask a logic bug.
Copy-ready fixes for Docker Compose and Kubernetes
The two manifests set explicit memory limits and a termination grace period. Use them as a baseline, then adjust the values to the measured working set of the service.
docker-compose.yml
Core dumps are controlled by ulimits and kernel.core_pattern on the host, not by the memory limit. If you enable them for debugging, mount a volume for the output and remove it after the investigation.
services:
app:
image: ghcr.io/acme/app:1.4.2
restart: on-failure:3
stop_grace_period: 20s
deploy:
resources:
limits:
memory: 1G
reservations:
memory: 512M
deployment.yaml
A container crash does not produce a core file you can read with kubectl by default. The node's core_pattern decides where it goes. Capture dmesg on the node and the application's crash log, then reproduce with the exact image digest and CPU architecture.
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
replicas: 2
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
terminationGracePeriodSeconds: 30
containers:
- name: app
image: ghcr.io/acme/app:1.4.2
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2000m"
memory: "1Gi"
env:
- name: GOTRACEBACK
value: "crash"
Capture the fault with symbols
A backtrace is the shortest path from 139 to the offending code.
ulimit -c unlimited
sysctl -w kernel.core_pattern=/var/crash/core.%e.%p
GOTRACEBACK=crash ./app
gdb /usr/local/bin/app /var/crash/core.app.1234Frequently asked questions
Does exit code 139 mean out of memory?
No. Out-of-memory kills are SIGKILL and exit 137, usually with OOMKilled true. Exit 139 is SIGSEGV, a fault caused by an invalid memory access. A memory limit can cause an allocation to fail, but a clean allocation failure normally surfaces as an application error, not a segfault.
How do I debug a SIGSEGV in a container?
Capture the core with a writable core_pattern and a volume, or use the node's coredumpctl. Then open it with gdb and the same binary plus debug symbols. Enable GOTRACEBACK=crash for Go programs. ASan or a debug build helps when the core cannot be captured.
Why do only some requests cause exit 139?
Memory-safety faults often depend on timing, input size or a race. A null pointer on a rarely used code path, a use-after-free under concurrency or a stack overflow on a deep input can all be intermittent. Reproduce with the same architecture and native dependencies rather than only the same application version.
Related exit codes, signals and network references
Follow the status you actually observed, then check the related port or calculator when the failure involves networking, exposure or firewall rules.
Reference basis: POSIX signal semantics (128 + n), Docker container exit status conventions, and Kubernetes container termination behaviour. Verify the exact behaviour against your runtime version before relying on it in an incident.
Last reviewed 2026-11-06 · All exit codes · Developer tools · Privacy