← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

PCNTL Signals in CLI PHP

PHP PHP 7.1+ Advanced
debt(d8/e3/b3/t7)
d8 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'silent in production until users hit it' (d8), slightly better than d9 because PHPStan and code patterns matching pcntl_signal/SIGTERM can flag missing dispatch calls, but in practice missing signal handling shows up only when SIGTERM is sent in production and jobs are interrupted mid-execution.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3), since the quick_fix is to add pcntl_async_signals(true), register a handler, and check a $running flag in the loop — a small focused change in the worker entry point, not a one-liner but well-contained.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3), since applies_to is limited to CLI/queue-worker contexts and the signal-handling pattern lives in the worker bootstrap; it doesn't shape the whole codebase but every long-running worker pays the tax.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7), grounded in misconception that scripts just terminate on SIGTERM and in common_mistakes — forgetting pcntl_signal_dispatch() in loops means handlers silently never fire, and trying to catch SIGKILL is futile; the 'obvious' setup is wrong in non-obvious ways.

About DEBT scoring →

TL;DR

The PCNTL extension lets CLI PHP scripts handle OS signals (SIGTERM, SIGINT, SIGUSR1) — enabling graceful shutdown and hot reload in long-running daemons.

Explanation

pcntl_signal(SIGTERM, $handler) registers a callback for OS signals. Signals are checked at tick points (declare(ticks=1)) or via pcntl_signal_dispatch() in loops. Key signals: SIGTERM (graceful shutdown request), SIGINT (Ctrl+C), SIGUSR1/USR2 (custom), SIGHUP (reload config). Pattern for queue workers: set a flag on SIGTERM, check flag in loop, finish current task then exit cleanly. PHP-FPM manages its own signals separately. The pcntl extension is CLI-only — not available in FPM/web context. PHP 8.1: async signals via pcntl_async_signals(true) removes need for ticks.

Common Misconception

PHP CLI scripts terminate immediately on SIGTERM — by default yes, but with pcntl_signal() you can intercept and handle gracefully.

Why It Matters

Graceful shutdown on SIGTERM prevents data corruption in queue workers and daemons — the job in progress completes before the process exits.

Common Mistakes

  • Not calling pcntl_signal_dispatch() in tight loops — signals accumulate but handler never fires.
  • Using ticks=1 on every statement — performance overhead. Use pcntl_async_signals(true) instead.
  • Handling SIGKILL — impossible to catch, always terminates immediately.

Code Examples

✗ Vulnerable
// Worker that can't shut down gracefully:
while (true) {
    $job = $queue->pop();
    processJob($job); // Killed mid-job on deploy
}
✓ Fixed
pcntl_async_signals(true); // PHP 8.1+ — no ticks needed
$running = true;
pcntl_signal(SIGTERM, function() use (&$running) {
    $running = false;
});
pcntl_signal(SIGINT, function() use (&$running) {
    $running = false;
});

while ($running) {
    $job = $queue->pop();
    if ($job) processJob($job); // Completes current job before exit
    else usleep(100000);
}

Added 23 Mar 2026
Views 69
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 2 pings W 1 ping T 2 pings F 2 pings S 3 pings S 7 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 1 ping T 0 pings F 0 pings S 1 ping S 0 pings M 1 ping T 0 pings W
No pings yet today
PetalBot 1
Scrapy 16 Perplexity 8 Amazonbot 7 ChatGPT 6 Google 5 SEMrush 5 Unknown AI 4 Ahrefs 3 Claude 2 PetalBot 2 Meta AI 1
crawler 53 crawler_json 3 pre-tracking 3
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Medium
⚡ Quick Fix
Use pcntl_async_signals(true) (PHP 8.1+) instead of ticks. Set a $running flag on SIGTERM/SIGINT. Check flag in worker loop to exit cleanly after current task.
📦 Applies To
PHP 7.1+ cli queue-worker
🔗 Prerequisites
🔍 Detection Hints
pcntl_signal|SIGTERM
Auto-detectable: ✗ No phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: File


✓ schema.org compliant