In POSIX-compliant operating systems, Signal 27 corresponds to SIGPROF (Profiling Timer Expired). While the phrase Signal 27 occasionally appears in regional law enforcement radio dispatch to denote a driver license status query, this engineering guide focuses strictly on POSIX Signal 27 within Linux, BSD, and Unix-like runtime environments.
Modern application runtimes, profilers, and kernel-level performance monitors interact continuously with operating system signals. Signal 27 serves a dedicated purpose: alerting a process that a designated block of combined user and system CPU time has elapsed. When unhandled or triggered unexpectedly, it causes sudden process termination, container crashes with exit code 155, or silent thread failure. This guide breaks down the architecture, generation mechanisms, diagnostics, and modern remediation strategies for Signal 27 across enterprise Linux environments in 2026.
Technical Architecture: What Signal 27 Represents in POSIX Systems
Under the POSIX.1-2017 and POSIX.1-2024 standards, signals are asynchronous notifications dispatched by the kernel to a process or specific thread to announce an event. Standard signals occupy numeric identifiers between 1 and 31 on standard x86_64, ARM64 (AArch64), and RISC-V Linux architectures.
Signal 27 is formally mapped to SIGPROF. Its default POSIX action is abnormal process termination (dumping core if core dump generation is enabled via resource limits).
Unlike real-time clocks that advance regardless of whether a machine is working or idle, SIGPROF operates on consumed execution time. It is driven by interval timers that decrement only when the operating system executes code on behalf of the target process. This design enables profilers to sample the call stack proportionally to actual CPU consumption rather than wall-clock passage, providing statistically valid performance bottlenecks without distorting metrics with external I/O waits.
Mechanics of Generation: How the Profiling Interval Timer Triggers Signal 27
To understand why a system emits Signal 27, engineers must inspect how the kernel manages process interval timers through POSIX system calls such as setitimer and timer_create.
The Linux kernel maintains three distinct timer domains for every execution context:
- Real-Time Domain (ITIMER_REAL): Decrements in real time across active and idle states, delivering Signal 14 (SIGALRM) upon expiration.
- Virtual Domain (ITIMER_VIRTUAL): Decrements exclusively when the process executes in user space, delivering Signal 26 (SIGVTALRM) upon expiration.
- Profiling Domain (ITIMER_PROF): Decrements when the process executes in user space AND when the kernel executes system calls or handles interrupts on behalf of that specific process. Upon expiration, it delivers Signal 27 (SIGPROF).
Kernel Delivery Mechanics
When the task profiling timer expires, the kernel marks a pending SIGPROF in the task struct of the thread group. At the next transition from kernel space back to user space—such as returning from a system call or hardware interrupt—the kernel inspects pending unblocked signals. If no custom signal handler is registered in the process sigaction table, the kernel executes the default disposition, immediately terminating the application.
Historically, utilities such as gprof relied heavily on configuring ITIMER_PROF to emit high-frequency SIGPROF ticks (often at 100 Hz or 1000 Hz). The application registered a custom signal handler that recorded the current Program Counter (PC) value before resuming execution. In modern runtimes, internal CPU samplers (including Go runtime pprof, Ruby stackprof, and legacy Java JVM profilers) still utilize SIGPROF internally to collect thread-level execution statistics.
Troubleshooting Unexpected Process Termination and Exit Code 155
When an application abruptly terminates due to an unhandled signal, Linux shells and container runtimes (such as containerd, Docker, and Kubernetes CRI-O) calculate the exit status using a standard formula: 128 plus the signal number.
For Signal 27, the fatal process exit code is calculated as follows:
128 + 27 = 155
If a Kubernetes Pod, Docker container, or systemd unit fails with Exit Code 155, the root cause is almost universally an unhandled SIGPROF.
Primary Causes of Unhandled Signal 27 Crashes
- Multi-Threaded Signal Routing Conflicts: In complex threaded applications (such as C++20 services, Go services, or Rust applications utilizing C FFI), the kernel delivers SIGPROF to any thread within the thread group that does not have the signal blocked. If a worker thread spawns without inheriting the parent thread signal mask, it receives SIGPROF without an active handler, invoking the default termination action.
- Forking Without Executing in Managed Runtimes: Runtimes like Go actively use SIGPROF for runtime CPU profiling. If a multi-threaded application forks without immediately executing an execve call, the child process inherits the active interval timer but often lacks the initialized runtime profiling handler, leading to instant failure upon the next timer tick.
- Interrupted System Calls (EINTR): While not causing termination directly, SIGPROF handlers that do not specify the SA_RESTART flag in their sigaction structure cause blocking system calls (such as epoll_wait, accept, read, or nanosleep) to fail immediately with error code EINTR. If application logic does not handle EINTR retries, the service crashes downstream due to unhandled I/O failures.
- Third-Party Profiler Injections: External tracing agents injected via LD_PRELOAD or sidecar containers may initialize ITIMER_PROF without properly cooperating with internal application runtimes, creating destructive race conditions over the SIGPROF handler.
Architectural Comparison: Profiling Timers vs. Alternative Linux Signals
Signal 27 exists alongside other timer signals. Selecting the correct timing mechanism is essential to prevent profiling artifacts and resource degradation.
| Signal Metric / Attribute | Signal 27 (SIGPROF) | Signal 26 (SIGVTALRM) | Signal 14 (SIGALRM) | Linux Perf / eBPF (Modern Alternative) |
|---|---|---|---|---|
| Numeric Value (x86_64/ARM64) | 27 | 26 | 14 | N/A (Kernel Ring Buffer) |
| POSIX Constant | SIGPROF | SIGVTALRM | SIGALRM | PERF_EVENT_IOC_ENABLE |
| Clock Source | User CPU + System (Kernel) CPU | User CPU Time Only | Wall Clock (Real-Time) | Hardware PMU Counters / Tracepoints |
| Default Action | Terminate Process | Terminate Process | Terminate Process | Zero Process Signal Interruption |
| Trigger Mechanism | ITIMER_PROF expiration | ITIMER_VIRTUAL expiration | ITIMER_REAL expiration | Hardware Interrupt / eBPF Bytecode |
| EINTR Interruption Risk | High (if SA_RESTART omitted) | High (if SA_RESTART omitted) | High (if SA_RESTART omitted) | None (Bypasses Signal Subsystem) |
| Production Suitability in 2026 | Moderate (Runtime-internal only) | Deprecated for general use | Active (Timeouts / Real alarms) | Enterprise Production Standard |
Modern Profiling Shifts: SIGPROF vs. Linux Perf and eBPF in 2026
While Signal 27 remains fundamentally supported across Unix kernels for backward compatibility and specialized language runtimes, the broader observability industry has significantly transitioned away from signal-based profiling in production.
Signal-based profiling suffers from inherent architectural limitations known as signal skew and frame pointer corruption. Because the kernel only delivers signals at safe kernel-to-user boundaries or instruction retirement thresholds, sample points naturally cluster around specific instructions rather than providing a pure statistical sample. Furthermore, executing user code inside a signal handler introduces strict constraints: only async-signal-safe functions can be called. Attempting memory allocation or acquiring non-reentrant mutexes within a SIGPROF handler triggers immediate deadlocks.
In modern 2026 production infrastructures, kernel-level sampling utilizing the perf_event_open interface and extended Berkeley Packet Filters (eBPF) represents the industry standard. Tools like Linux perf, continuous profiling engines, and eBPF agents capture stack traces by reading hardware Performance Monitoring Unit (PMU) counters directly. This completely bypasses the POSIX signal architecture, eliminating Exit Code 155 crashes, removing EINTR system call disruptions, and preventing profiling overhead inside mission-critical customer pathways.
Step-by-Step Remediation: Handling and Masking Signal 27
When diagnosing or mitigating unwanted Signal 27 events in legacy systems or specialized runtime environments, follow this disciplined troubleshooting procedure.
Step 1: Identify the Triggering Subsystem
To determine which entity is configuring ITIMER_PROF, run an execution trace against the failing binary using strace:
Track all timer configurations and signal dispositions by filtering for setitimer, timer_create, and rt_sigaction system calls. Look specifically for calls passing ITIMER_PROF. The output will reveal the precise thread and library setting the microsecond expiration interval.
Step 2: Establish Async-Signal-Safe Handlers
If an application must utilize Signal 27 for custom internal diagnostics, the handler must be configured using the modern rt_sigaction interface with explicit flags:
- Enable SA_RESTART: Always set the SA_RESTART flag in the sa_flags field. This instructs the kernel to automatically resume interrupted system calls rather than failing them with EINTR.
- Enable SA_SIGINFO: Use an extended three-argument handler signature (siginfo_t) to inspect the originating process ID (si_pid) and verify whether the signal arrived from an interval timer (SI_TIMER) or an external user command (SI_USER).
- Enforce Strict Reentrancy: Never invoke functions like malloc, free, printf, or standard logging frameworks inside the SIGPROF handler. Restrict actions to atomic state changes or raw writes to pre-allocated pipes.
Step 3: Block SIGPROF in Worker Threads
In multi-threaded environments where profiling is handled by a single dedicated agent thread, block Signal 27 across all newly created application threads:
- Configure a signal set (sigset_t) containing SIGPROF.
- Apply the signal mask using pthread_sigmask with the SIG_BLOCK operation prior to spawning worker threads.
- Allow worker threads to inherit the blocked mask, ensuring that if an interval timer fires, the signal remains pending until handled explicitly by an unmasked consumer thread or runtime supervisor.
Operational Warning on Ignoring SIGPROF
Setting the action of Signal 27 to SIG_IGN will prevent process termination, but it will not stop the underlying kernel timer if setitimer remains active. The kernel will continue consuming CPU cycles generating and instantly discarding signals on every tick. The proper engineering remedy is always to disable the timer itself by passing a zeroed itimerval structure to ITIMER_PROF.
Frequently Asked Questions
What does Signal 27 mean when a Linux process terminates?
Signal 27 indicates that the operating system sent SIGPROF (Profiling Timer Expired) to the process, and because the process had no handler defined, the kernel executed the default action to terminate it. When captured in modern container environments, this crash displays as Exit Code 155 (128 plus 27).
Why am I getting an Exit Code 155 in my Docker container or Kubernetes Pod?
Exit Code 155 signifies that your containerized application was killed by Signal 27 (SIGPROF). This typically occurs when an embedded CPU profiling agent, language runtime profiler (such as Go pprof or Python cProfile), or legacy monitoring script initiates an interval timer that fires inside a thread without an active, registered signal handler.
What is the difference between Signal 27 (SIGPROF) and Signal 14 (SIGALRM)?
Signal 14 (SIGALRM) tracks wall-clock elapsed time via ITIMER_REAL regardless of whether the CPU is busy or idle, whereas Signal 27 (SIGPROF) tracks only the CPU time consumed by the process in both user and kernel modes via ITIMER_PROF. Signal 14 is primarily used for operational timeouts, while Signal 27 is reserved for performance profiling.
Can Signal 27 be safely ignored or blocked?
Yes, Signal 27 can be caught, blocked, or ignored using standard POSIX signal management functions like sigprocmask, pthread_sigmask, or sigaction. However, if an external library or internal profiler configured an active ITIMER_PROF, ignoring the signal without disabling the underlying timer creates unnecessary CPU overhead as the kernel continues generating discarded signal events.
Does Signal 27 have a different meaning outside of computer operating systems?
Yes, in public safety and police radio 10-codes, Signal 27 is commonly used by emergency dispatchers in specific jurisdictions (such as the Florida Highway Patrol) to refer to a driver license check or wanted person status inquiry. In computer science, cloud architecture, and software engineering, Signal 27 refers exclusively to the POSIX SIGPROF signal.
Operational Next Steps for Systems Engineers
If your systems are encountering intermittent Exit Code 155 errors or thread stalls associated with Signal 27, begin by auditing your current monitoring and profiling toolchain. Deprecate legacy timer-driven user-space sampling in favor of modern eBPF continuous profilers natively integrated into the Linux 6.x kernel series. Ensure all microservices implement standard POSIX signal isolation on worker threads, and verify that any profiling tools deployed across production clusters handle system call interruption cleanly to maintain resilient, zero-downtime operations.