Find Segfaults in PHP like a boss
Section intitulée a-bit-of-historyA bit of history
Sometimes, a segfault happens, but you don’t know where, and your PHP installation does not have tools to find it. Or sometime, you think PHP is hanging, but you don’t know where. You may use xdebug, but you don’t want to click so many times on the « next call » button.
To address theses issues, I used to use this hack.
register_tick_function(function() {
$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1);
$last = reset($bt);
$info = sprintf("%s +%d\n", $last['file'], $last['line']);
file_put_contents('/tmp/segfault.txt', $info, FILE_APPEND);
// or
// file_put_contents('php://output', $info, FILE_APPEND);
});
declare(ticks=1);
The code is pretty small but it could appear really weird. Don’t worry, I will explain it.
-
We register a tick function. A tick is an event emitted by PHP when a very low-level (tickable) statements is executed. This function will be executed on each PHP Tick and will print the last executed line.
-
We tell PHP to fire an event for all possible tick.
-
Profit… Thanks to that, it’s possible to find the last successfully executed line.
But, what I did not know, is that it worked because of a PHP Bug: declare(ticks=1)
is not supposed
to leak to other files. This has been fixed in PHP 7.0 and so my hack does not
work anymore.
Section intitulée let-s-use-a-strike-bigger-strike-cleaner-hackLet’s use a bigger cleaner hack
So If I want to continue to use this debug method, I need to put by hand
declare(ticks=1)
on every PHP files… Boring! I could write a simple tool
that will do that for me but I don’t want to modify all my vendors.
So I decided to use PHP Stream Wrapper and Stream Filter. Theses PHP features are not really well known, but they are very powerful. I encourage you to read more about it.
This new implementation replaces the default file
and phar
stream wrapper
implementation of PHP to be able to automatically add declare(ticks=1)
on each
PHP file. But this is done only in memory, not physically on the disk.
Section intitulée usageUsage
To use it, copy the HardCoreDebugLogger.php
file somewhere on your disk and
then add the following line in your code:
require '/path/to/HardCoreDebugLogger.php'
HardCoreDebugLogger::register();
By default, the traces will be displayed on STDOUT, but you can change it to save it a file:
require '/path/to/HardCoreDebugLogger.php'
HardCoreDebugLogger::register('/tmp/trace.txt');
Section intitulée demoDemo?
First, you will learn how to generate a segfault with PHP. You should not try to reproduce it at home!
// require __DIR__.'/HardCoreDebugLogger.php';
// declare(ticks=1); // We need tick in this file
// HardCoreDebugLogger::register();
function a()
{
b();
}
function b()
{
c();
}
function c()
{
$a = 1 + 2;
"".(new Crash());
}
class Crash
{
public function __tostring()
{
return "".$this;
}
}
a();
If you try to execute this code, you will get the following:
$ php segfault.php
Segmentation fault (core dumped)
Not easy to find the segfault, isn’t it? And now, imagine you have 100 000 lines of codes 😱
We need to uncomment the 3 first lines to get the following:
$ php segfault.php
1555494674.7385 /tmp/56dfc48fb7e807dd2a229813da89a0dc/segfault.php +5
1555494674.7385 /tmp/56dfc48fb7e807dd2a229813da89a0dc/segfault.php +10
1555494674.7385 /tmp/56dfc48fb7e807dd2a229813da89a0dc/segfault.php +16
1555494674.7385 /tmp/56dfc48fb7e807dd2a229813da89a0dc/segfault.php +23
1555494674.7385 /tmp/56dfc48fb7e807dd2a229813da89a0dc/segfault.php +25
1555494674.7386 /tmp/56dfc48fb7e807dd2a229813da89a0dc/segfault.php +20
Segmentation fault (core dumped)
And now, we know the last successful executed line is the line 20. So the segfault should be triggered by:
"".(new Crash());
Section intitulée creditCredit
Writing a Stream Wrapper is boring, so I would like to credit Anthony Ferrara for his work on php-preprocessor.
Commentaires et discussions
Ces clients ont profité de notre expertise

Afin de poursuivre son déploiement sur le Web, Arte a souhaité être accompagné dans le développement de son API REST “OPA” (API destinée à exposer les programmes et le catalogue vidéo de la chaine). En collaboration avec l’équipe technique Arte, JoliCode a mené un travail spécifique à l’amélioration des performances et de la fiabilité de l’API. Ces…

Dans le cadre d’une refonte complète de son architecture Web, le journal en ligne Mediapart a sollicité l’expertise de JoliCode afin d’accompagner ses équipes. Mediapart.fr est un des rares journaux 100% en ligne qui n’appartient qu’à ses lecteurs qui amène un fort traffic authentifiés et donc difficilement cachable. Pour effectuer cette migration, …

À l’occasion de la 12e édition du concours Europan Europe, JoliCode a conçu la plateforme technique du concours. Ce site permet la présentation des différents sites pour lesquels il y a un appel à projets, et encadre le processus de recueil des projets soumis par des milliers d’architectes candidats. L’application gère également toute la partie post-concours…