2022-01-09
A long-running process was consuming high CPU, and I needed to figure out what was happening. Adding the ability to generate a stack trace by sending the process a signal helped isolate what was going on.
This script demonstrates how a stack trace can be generated when a PHP process receives the SIGHUP signal. Trapping other signals would work as well.
<?php
declare(strict_types=1);
pcntl_async_signals(true);
pcntl_signal(SIGHUP, function ($signal) {
echo "HUP! {$signal} \n";
error_log((new Exception())->getTraceAsString());
});
(new class
{
function __invoke()
{
printf("kill -s HUP %d\n", getmypid());
while (true) {
sleep(255);
}
}
})();
An example of the script in action:
# Running the script will print a command to run to send a signal to the
# running process.
$ php script.php
kill -s HUP 867403
# In another terminal, we run the command while the script is running:
$ kill -s HUP 867403
# The original process outputs that it received the signal, and prints a
# stack trace of the code that was executing when the signal was
# received.
HUP! 1
#0 /path/to/script.php(18): {closure}()
#1 /path/to/script.php(12): class@anonymous->__invoke()
#2 {main}