BreadcrumbHomeResourcesBlog Debugging PHP Segmentation Faults November 30, 2022 Debugging PHP Segmentation FaultsDebuggingBy Slavey KaradzhovDebugging PHP can be hard, but debugging PHP segmentation faults (segfaults) in the PHP interpreter or its modules is even harder. In this article, we look at how PHP developers (with no prior C knowledge) can analyze, understand, and fix PHP segfaults. Table of ContentsPHP Segmentation Fault OverviewHow to Analyze a PHP Segmentation FaultHow to Find the Cause of the Segmentation FaultDebugging PHP BuildsAnalyzing Your PHP Segmentation FaultsRuntime / Live Debugging PHP Segmentation FaultsPost-Mortem Debugging PHP Segmentation FaultsFinal ThoughtsTable of Contents1 - PHP Segmentation Fault Overview2 - How to Analyze a PHP Segmentation Fault3 - How to Find the Cause of the Segmentation Fault4 - Debugging PHP Builds5 - Analyzing Your PHP Segmentation Faults6 - Runtime / Live Debugging PHP Segmentation Faults7 - Post-Mortem Debugging PHP Segmentation Faults8 - Final ThoughtsBack to topPHP Segmentation Fault OverviewA segfault in the PHP interpreter or one of its modules is something that rarely happens. But, when it happens, it can cause a lot of frustration and confusion. A PHP developer might feel left in the dark when a segfault happens.What Is a PHP Segmentation Fault?A segmentation fault, or segfault, is any condition whereby the application has attempted to access a restricted area of memory.These crashes are often associated with a file named core. Segfaults are often caused by a program trying to read or write an illegal memory location.Are PHP Segmentation Faults Dangerous?No, but they require a bit of preparation to analyze — and it is rarely possible to analyze completely with PHP debuggers.ZendHQ Makes Debugging PHP Applications EasyZendHQ offers advanced debugging functionality for a seamless PHP development experience. Try free today, or schedule a custom demo for your team, via the links below.Try for Free SChedule a ZendHQ DemoBack to topHow to Analyze a PHP Segmentation FaultA segmentation fault can be due to a hardware issue, software issue (e.g., library incompatibilities), or a code issue. To successfully analyze a segfault, you should be able to reproduce the issue on the same server where it happened (or still happens) and with the same software environment. This means that you should be able to isolate the server where the issue happens, determine if the issue is reproducible throughout a cluster of PHP servers, and add instrumentation to that server.Back to topHow to Find the Cause of the Segmentation FaultFinding 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.Installing the GNU Debugger (GDB)For the purposes of this article, we will be installing GDB to find segfaults. According to the GDB entry on the Sourceware website, GDB "allows you to see what is going on `inside' another program while it executes -- or what another program was doing at the moment it crashed."Most of the popular operating systems have already pre-built packages for GDB and can be installed with a simple command. For the purposes of this article, we will use Ubuntu as our operating system (OS).In Ubuntu GDB can be installed using the command below:sudo apt-get install gdbGDB has to be installed and run on the server where the issue is happening.NOTEIf PHP is running on an embedded system then it might not be possible to run GDB directly on the same device. For such cases it will suffice to compile and run a gdbserver on the embedded system. In this article we will not cover this topic. Those of you that are interested can find more information on gdbserver hereBack to topDebugging PHP BuildsIn order to get meaningful information from a binary, you will also need to have the debug symbols for the PHP binary and its modules.Use Prebuilt Debug SymbolsIf you are using PHP distributions like Zend Server, you can just install additional packages with all pre-built debug symbols.In the case of Zend Server this can be done by typing:sudo apt-get install zend-server-dbgFor ZendPHP, it would look similar to this:bash apt install $(apt list --installed | grep php8.2 | cut -d"/" -f 1 | awk '{print $0"-dbgsym"}')Note that you would need to substitute in your desired PHP version into the command line based on what you are running in production.It is worth checking if your distribution provides debug symbols for PHP before trying to compile a debug build. If the OS does not provide them, then you can read the next option below.Compile a Debug Build of the PHP InterpreterIf your operating system does not provide easy access to debug symbols for the PHP interpreter then you can try to build a PHP debug build yourself. Be warned, tt requires more steps than just installing the debug symbols and additional software is needed for the compilation of the PHP interpreter.Read more about setting up a PHP build environment >> The step below installs the additional software for Ubuntu:sudo apt-get install build-essential autoconf automake bison flex re2c \ libtool make pkgconf git libxml2-dev libsqlite3-dev The steps below describe how to download the PHP source code for the version that you are interested in. In this article we will be using PHP version 8.2.0.cd <your-development-directory>/ git clone https://github.com/php/php-src.git --branch=PHP-8.2.0A new php-src directory will be created. In this directory, you can execute the following commands to prepare the 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 The important piece from the snippet above are `--enable-debug`, which instructs the build system to create a debug version of the PHP interpreter and the desired modules; and `CFLAGS="-DDEBUG_ZEND=2"`, which instructs the compiler to build the interpreter with more debugging statements. This can help us better analyze the root cause of the problem.It's important to note that the command above compiles only PHP-CGI binary and the json module. If you need more modules or other binary, e.g. fpm, then be sure to read the article linked above.Back to topAnalyzing Your PHP Segmentation FaultsFor both runtime and post-mortem analysis we will be using GDB. In the root of the PHP sources directory you will find a file named .gdbinit. This file helps us understand the PHP functions that were involved in the event leading to a segfault. For PHP version 8.2.0 the .gdbinit file can be downloaded here.The analysis must be done on the same machine where the segfault happens. This is because the machine will have the same hardware and memory layout, operating system, binary files, libraries, PHP version, extensions, and configurations.Back to topRuntime / Live Debugging PHP Segmentation FaultsRuntime debugging is useful when the segfaults happen frequently, or are reproducible.In order for a runtime debugging to be successful we have to limit the number of PHP processes responsible for our segfaulting application to a minimum. It is possible to instruct apache or FastCGI to have only one process.Once this is done we can run the following command to debug a running PHP process:gdb -x .gdbinit -p <pid-of-php-process>In the command above, <pid-of-php-process> has to be replaced with the actual Process ID (PID) of the running PHP process. When the GDB attaches to a running process the process will be paused. To unpause it you have to type the following command in GDB:continueNow reproduce the steps that are leading to a segfault. At some point GDB will notify you that a segfault has occurred. You can use the following commands to understand what has caused the segfault from the PHP application.zbacktraceA sample output looks like:If the command above does not produce a helpful information then the following two will definitely have a lot of useful informationbacktrace backtrace fullThe newly gathered information can be sent to the PHP Core developers or a module developer in order to help them fix the issue. Or you can work-around the issue by using other PHP functions that can produce the same results as the ones causing segfault.Back to topPost-Mortem Debugging PHP Segmentation FaultsDebugging PHP post-mortems involve inspecting the state of the PHP interpreter and its modules that have crashed, in order to determine the conditions that lead to the failure.The default action for a segmentation fault or bus error is abnormal termination of the process that triggered it. As the Wiki entry for Segmentation Faults explains, “a core file may be generated to aid debugging, and other platform-dependent actions may also be performed.” A generated code dump file can be quite big in size. In most operating systems generating a core dump file is disabled by default. To enable it on Ubuntu (or any other Linux distribution) you have to run the following command before running the application:ulimit -c unlimitedIf your PHP interpreter is running as a service then you have to instruct the service to allow core dumps. For further information, we recommend reading this article on how to understand and configure core dumps.The rest of the commands are similar to the runtime debugging. In order to start GDB, we need to pass the executable as the first parameter, then the code dump as the second parameter:gdb -batch -x .gdbinit $binary $dumpAs an example, in situations where the PHP interpreter is running as a module in Apache you would use:gdb -batch -x .gdbinit /usr/sbin/apache2 /var/c/ore123Or, for situations where PHP is running as a CGI/FastCGI service:gdb -batch -x .gdbinit /usr/bin/php-cgi /var/c/ore123Back to topFinal ThoughtsIn this article we showed steps for finding, analyzing, and debugging PHP segmentation faults using GDB and Zend Server. Stay tuned to the Zend blog for future articles on debugging PHP using ZendPHP and ZendHQ.Additional ResourcesBlog - PHP Debugging: Go Beyond Step Debuggers With ZendHQBlog - Why Good PHP Monitoring MattersBlog - Introducing JobQueue for ZendPHPBlog - PHP Code Tracing With ZendHQ and ZendPHPBlog - Finding and Fixing PHP Errors in ProductionBlog - Move Your Development Forward With Reverse DebuggingBlog - How to Use Apache HTTPD With php-fpm and mod_phpOn-Demand Webinar - PHP Observability and Orchestration With ZendHQWhite Paper - Writing PHP ExtensionsBack to top
Slavey Karadzhov Senior Consultant, Zend by Perforce Slavey is a full-time senior consultant, trainer, and helping hand at Zend by Perforce. He has many years of experience working with PHP (v3 .. v8), Zend Framework/Laminas, and a galaxy of programming languages, including Python, Perl, Java, JavaScript, C/C++, and more.