From c9ce233f0831118c6aa23197bad9ab07355a6ab6 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 4 Nov 2025 09:16:22 +0800 Subject: [PATCH] MDL-87079 core: Call existing pcntl handlers Whilst `register_shutdown_function` works as a queue, `pcntl_signal` does not. To preserve the behaviour of existing signal handlers, as are typically found in CLI wrappers like PHPUnit and Behat, we should store any existing handler --- lib/classes/shutdown_manager.php | 22 ++++++++++++++++++++-- lib/upgrade.txt | 3 +++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/lib/classes/shutdown_manager.php b/lib/classes/shutdown_manager.php index 5f0aec5dcf6..7642526cec4 100644 --- a/lib/classes/shutdown_manager.php +++ b/lib/classes/shutdown_manager.php @@ -39,6 +39,9 @@ class core_shutdown_manager { /** @var bool is this manager already registered? */ protected static $registered = false; + /** @var array A list of pcntl handlers */ + protected static array $pcntlhandlers = []; + /** * Register self as main shutdown handler. * @@ -58,8 +61,19 @@ class core_shutdown_manager { if (CLI_SCRIPT && extension_loaded('pcntl') && function_exists('pcntl_async_signals')) { // We capture and handle SIGINT (Ctrl+C) and SIGTERM (termination requested). pcntl_async_signals(true); - pcntl_signal(SIGINT, ['core_shutdown_manager', 'signal_handler']); - pcntl_signal(SIGTERM, ['core_shutdown_manager', 'signal_handler']); + + $signals = [SIGINT, SIGTERM]; + + foreach ($signals as $signal) { + if (function_exists('pcntl_signal_get_handler')) { + $handler = pcntl_signal_get_handler($signal); + if (is_callable($handler)) { + // We can restore the original handler later if needed. + self::$pcntlhandlers[$signal] = $handler; + } + } + pcntl_signal($signal, ['core_shutdown_manager', 'signal_handler']); + } } } @@ -106,6 +120,10 @@ class core_shutdown_manager { error_log('Exception ignored in signal function ' . get_callable_name($callback) . ': ' . $e->getMessage()); } } + if (array_key_exists($signo, self::$pcntlhandlers)) { + $handler = self::$pcntlhandlers[$signo]; + $handler($signo); + } if ($shouldexit) { exit ($exitcode); diff --git a/lib/upgrade.txt b/lib/upgrade.txt index dad08af27b6..c8759887258 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -1,6 +1,9 @@ This files describes API changes in core libraries and APIs, information provided here is intended especially for developers. +=== 4.1.22 === +* message: When responding to pcntl signals, call existing signal handlers. + === 4.1.21 === * Moodle's Behat `::execute()` method now supports the use of array callable syntax for calling other steps.