
Déboguer PHP peut être difficile, mais déboguer les erreurs de segmentation PHP (segfaults) dans l'interpréteur PHP ou ses modules est encore plus difficile. Dans cet article, nous examinons comment les développeurs PHP (sans aucune connaissance préalable en C) peuvent analyser, comprendre et corriger les erreurs de segmentation PHP.
- Présentation des erreurs de segmentation PHP
- Comment analyser une erreur de segmentation PHP
- Comment trouver la cause du défaut de segmentation
- Débogage des builds PHP
- Analyser vos défauts de segmentation PHP
- Débogage post-mortem des erreurs de segmentation PHP
- Dernières pensées
Présentation des erreurs de segmentation PHP
Une erreur de segmentation dans l'interpréteur PHP ou l'un de ses modules est quelque chose qui arrive rarement. Mais lorsque cela se produit, cela peut engendrer beaucoup de frustration et de confusion. Un développeur PHP peut se sentir laissé dans le flou lorsqu'une erreur de segmentation se produit.
What Is a PHP Segmentation Fault?
Une erreur de segmentation, ou erreur de segmentation, est toute condition dans laquelle l'application a tenté d'accéder à une zone restreinte de mémoire.
Ces crashs sont souvent associés à un fichier nommé core. Les erreurs de segmentation sont souvent causées par un programme essayant de lire ou d'écrire un emplacement mémoire illégal.
Les erreurs de segmentation PHP sont-elles dangereuses ?
No, but they require a bit of preparation to analyze — and it is rarely possible to analyze completely with PHP debuggers.
Easily Debug Your PHP Applications With ZendHQ and ZRay Zend Server ZRay and ZendPHP ZendHQ offer advanced debugging functionality for a seamless PHP development experience. Try free today to see how they work in action.
TRY ZENDPHP TRY ZEND SERVER
Comment analyser une erreur de segmentation PHP
Une erreur de segmentation peut être due à un problème matériel, un problème logiciel (par exemple, des incompatibilités de bibliothèque) ou un problème de code. Pour analyser avec succès une erreur de segmentation, vous devez être capable de reproduire le problème sur le même serveur où il s'est produit (ou se produit encore) et avec le même environnement logiciel. Cela signifie que vous devriez être en mesure d'isoler le serveur sur lequel le problème se produit, de déterminer si le problème est reproductible dans un cluster de serveurs PHP et d'ajouter une instrumentation à ce serveur.
Comment trouver la cause du défaut de segmentation
Finding the cause of a segmentation fault in PHP is dependent on that fault being reproducible. For example, if you make a POST request to a specific URL with special form data, then you can have a runtime debugging session. If such issues are happening very rarely then you can try to analyze the segfault after it has happened.
Installation du débogueur GNU (GDB)
Pour les besoins de cet article, nous installerons GDB pour rechercher les erreurs de segmentation. Selon l'entrée GDB sur le site Web Sourceware, GDB "vous permet de voir ce qui se passe à l'intérieur d'un autre programme pendant son exécution - ou ce qu'un autre programme faisait au moment où il plante."
La plupart des systèmes d'exploitation populaires disposent déjà de packages prédéfinis pour GDB et peuvent être installés avec une simple commande. Pour les besoins de cet article, nous utiliserons Ubuntu comme système d'exploitation (OS).
Dans Ubuntu, GDB peut être installé à l'aide de la commande ci-dessous :
sudo apt-get install gdb
GDB doit être installé et exécuté sur le serveur sur lequel le problème se produit.
NOTE
Si PHP s'exécute sur un système embarqué, il n'est peut-être pas possible d'exécuter GDB directement sur le même appareil. Dans de tels cas, il suffira de compiler et d'exécuter un gdbserver sur le système embarqué. Dans cet article, nous n'aborderons pas ce sujet. Ceux d'entre vous qui sont intéressés peuvent trouver plus d'informations sur gdbserver ici
Débogage des builds PHP
Afin d'obtenir des informations significatives à partir d'un binaire, vous aurez également besoin des symboles de débogage du binaire PHP et de ses modules.
Utiliser des symboles de débogage prédéfinis
Si vous utilisez des distributions PHP comme Zend Server, vous pouvez simplement installer des packages supplémentaires avec tous les symboles de débogage prédéfinis.
Dans le cas de Zend Server, cela peut être fait en tapant :
sudo apt-get install zend-server-dbg
Pour ZendPHP, cela ressemblerait à ceci :
apt install $(apt list --installed | grep php8.2 | cut -d"/" -f 1 | awk '{print $0"-dbgsym"}')
Notez que vous devrez remplacer la version PHP souhaitée dans la ligne de commande en fonction de ce que vous exécutez en production.
Il vaut la peine de vérifier si votre distribution fournit des symboles de débogage pour PHP avant d'essayer de compiler une version de débogage. Si le système d'exploitation ne les fournit pas, vous pouvez lire l'option suivante ci-dessous.
Compiler une version de débogage de l'interpréteur PHP
Si votre système d'exploitation ne fournit pas un accès facile aux symboles de débogage pour l'interpréteur PHP, vous pouvez essayer de créer vous-même une version de débogage PHP. Attention, cela nécessite plus d'étapes que la simple installation des symboles de débogage et un logiciel supplémentaire est nécessaire pour la compilation de l'interpréteur PHP.
En savoir plus sur la configuration d'un environnement de build PHP >>
L'étape ci-dessous installe le logiciel supplémentaire pour Ubuntu :
sudo apt-get install build-essential autoconf automake bison flex re2c \
libtool make pkgconf git libxml2-dev libsqlite3-dev
Les étapes ci-dessous décrivent comment télécharger le code source PHP pour la version qui vous intéresse. Dans cet article, nous utiliserons PHP version 8.2.0.
cd <votre-répertoire-de-développement>/
git clone https://github.com/php/php-src.git --branch=PHP-8.2.0
Un nouveau répertoire php-src sera créé. Dans ce répertoire, vous pouvez exécuter les commandes suivantes pour préparer la compilation :
cd php-src
./buildconf --force
./configure \
--disable-all \
--enable-debug \
--enable-cgi \
--enable-shared \
--enable-json=shared \
CFLAGS="-DDEBUG_ZEND=2"
make && make install
L'élément important de l'extrait ci-dessus est --enable-debug
, qui demande au système de build de créer une version de débogage de l'interpréteur PHP et des modules souhaités ; et CFLAGS="-DDEBUG_ZEND=2"
, qui demande au compilateur de construire l'interpréteur avec plus d'instructions de débogage. Cela peut nous aider à mieux analyser la cause profonde du problème.
It is important to note that the above command only compiles the PHP-CGI binary and json module. If you need more modules or other binaries, e.g. fpm, so be sure to read the article linked above.
Analyser vos défauts de segmentation PHP
Pour l'analyse d'exécution et post-mortem, nous utiliserons GDB. A la racine du répertoire des sources PHP vous trouverez un fichier nommé .gdbinit. Ce fichier nous aide à comprendre les fonctions PHP impliquées dans l'événement conduisant à une erreur de segmentation. Pour PHP version 8.2.0, le fichier .gdbinit peut être téléchargé ici.
L'analyse doit être effectuée sur la même machine sur laquelle se produit le segfault. En effet, la machine aura la même disposition matérielle et mémoire, le même système d'exploitation, les mêmes fichiers binaires, bibliothèques, version PHP, extensions et configurations.
Runtime / Live Debugging PHP Segmentation Faults Runtime debugging is useful when the segfaults happen frequently, or are reproducible.
Pour qu'un débogage d'exécution réussisse, nous devons limiter au minimum le nombre de processus PHP responsables de notre application segfaulting. Il est possible de demander à Apache ou FastCGI de n'avoir qu'un seul processus.
Une fois cela fait, nous pouvons exécuter la commande suivante pour déboguer un processus PHP en cours d'exécution :
gdb -x .gdbinit -p <pid-of-php-process>
Dans la commande ci-dessus, doit être remplacé par l'ID de processus (PID) réel du processus PHP en cours d'exécution. Lorsque le GDB s'attache à un processus en cours d'exécution, le processus est mis en pause. Pour le réactiver, vous devez taper la commande suivante dans GDB :
continue
Reproduisez maintenant les étapes qui conduisent à une erreur de segmentation. À un moment donné, GDB vous informera qu'une erreur de segmentation s'est produite. Vous pouvez utiliser les commandes suivantes pour comprendre la cause de l'erreur de segmentation de l'application PHP.
zbacktrace
Un exemple de sortie ressemble à :
exemple de sortie zbacktrace
pour une erreur de segmentation PHP
Si la commande ci-dessus ne produit pas d'informations utiles, les deux suivantes contiendront certainement de nombreuses informations utiles.
backtrace
backtrace full
Les informations nouvellement collectées peuvent être envoyées aux développeurs PHP Core ou à un développeur de module afin de les aider à résoudre le problème. Ou vous pouvez contourner le problème en utilisant d'autres fonctions PHP qui peuvent produire les mêmes résultats que celles provoquant une erreur de segmentation.
Débogage post-mortem des erreurs de segmentation PHP
Le débogage post-mortem consiste à inspecter l'état de l'interpréteur PHP et de ses modules qui ont planté, afin de déterminer les conditions qui ont conduit à la panne.
L'action par défaut en cas d'erreur de segmentation ou d'erreur de bus est la fin anormale du processus qui l'a déclenchée.
Comme l'explique l'entrée Wiki pour les défauts de segmentation, "un fichier principal peut être généré pour faciliter le débogage, et d'autres actions dépendantes de la plate-forme peuvent également être effectuées".
Un fichier de vidage de code généré peut être assez volumineux. Dans la plupart des systèmes d'exploitation, la génération d'un fichier core dump est désactivée par défaut. Pour l'activer sur Ubuntu (ou toute autre distribution Linux), vous devez exécuter la commande suivante avant d'exécuter l'application :
ulimit -c unlimited
Si votre interpréteur PHP fonctionne en tant que service, vous devez demander au service d'autoriser les core dumps. Pour plus d'informations, nous vous recommandons de lire cet article sur la façon de comprendre et de configurer les core dumps.
Le reste des commandes est similaire au débogage d’exécution. Afin de démarrer GDB, nous devons passer l'exécutable en premier paramètre, puis le code dump en deuxième paramètre :
gdb -batch -x .gdbinit $binary $dump
À titre d'exemple, dans les situations où l'interpréteur PHP s'exécute en tant que module dans Apache, vous utiliserez :
gdb -batch -x .gdbinit /usr/sbin/apache2 /var/c/ore123
Or, for situations where PHP is running as a CGI/FastCGI service:
gdb -batch -x .gdbinit /usr/bin/php-cgi /var/c/ore123
Dernières pensées
Dans cet article, nous avons montré comment rechercher, analyser et déboguer les erreurs de segmentation PHP à l'aide de GDB et Zend Server. Restez à l'écoute du blog Zend pour de futurs articles sur la façon de déboguer PHP à l'aide de ZendPHP et ZendHQ.
Auteur
Franck DAKIA
Code anyway
Restez à jour
Seules les mises à jour importantes seront envoyées, votre email ne sera jamais partagé ou vendu à quelqu'un d'autre.
Commentaires récents
Partagez
Tags