在 PHP 中執行不可控的第三方代碼、複雜計算或外部調用時,若無超時機制,進程可能長時間阻塞,導致服務不可用。本文介紹一種利用 pcntl 擴展的時鐘信號(SIGALRM)結合異常捕獲實現函數級超時控制的方法。
pcntl_alarm(秒數)pcntl_signal(SIGALRM, function() { throw new Exception('Timeout'); })try-catch 塊中執行目標函數pcntl_alarm(0) 取消鬧鐘<?php
declare(ticks = 1); // 必須聲明,使信號處理函數能在 tick 中被調用
function longTask() {
sleep(10);
echo "longTask finished\n";
}
function normalTask() {
echo "Stop\n";
}
function signalHandler($signo) {
throw new Exception("Execution timeout");
}
try {
pcntl_signal(SIGALRM, "signalHandler");
pcntl_alarm(1); // 1秒超時
longTask(); // 將超時
pcntl_alarm(0); // 正常結束取消鬧鐘
} catch (Exception $e) {
echo "Caught: " . $e->getMessage() . "\n";
}
normalTask(); // 繼續執行後續代碼
longTask(); // 再次調用(無超時控制)
normalTask();
?>
PHP 只有在聲明 declare(ticks = 1) 時,才會在每條低級語句執行後檢查是否有待處理信號。否則信號處理函數不會被及時調用。
設置秒級鬧鐘,到期後向進程發送 SIGALRM 信號。參數為 0 時取消當前鬧鐘。
信號處理函數中拋出的異常會中斷當前函數執行,直接跳轉到外層 catch 塊,實現「強制終止」效果。
對於 Web 環境或更精細控制,建議使用:
set_time_limit()(僅限腳本整體最大執行時間)