How to Debug
Bizarre PHP Bugs
Photo by Dmitry Bukhantsov
Slide 2
Slide 2 text
Kévin Dunglas
➔ Co-founder of Les-Tilleuls.coop
➔ Creator of FrankenPHP and API Platform
➔ Co-maintainer of Caddy and Symfony
➔ Contributor to PHP, and by necessity, to Xdebug 🐞
@dunglas
Slide 3
Slide 3 text
PHP, Web and Cloud Experts
➔ Development: PHP, JS, Go, Rust, C...
➔ DevOps and SRE
➔ Consultancy and maintenance
➔ Agile management, UX and UI
design…
➔ contact@les-tilleuls.coop 💌
Slide 4
Slide 4 text
Where's the Bug?
Slide 5
Slide 5 text
As a user: is the bug in my code or in the library I'm using?
There might be a
bug in the lib
(but could be in your
code)
The bug is
probably in your
code
(but could be in the lib)
Is this lib
popular?
Has a new
version been
published
recently?
Does downgrading
solve this issue?
Are you using
the lib in a
weird or
advanced way?
Have others
users reported
this bug?
YES
NO
YES
NO
YES
NO
YES
NO
NO
YES
Slide 6
Slide 6 text
As a maintainer: is the bug in my lib or in user’s code?
The bug is likely in
their code
It is a regular
contributor?
How many users
reported the bug?
SOME
MANY
A
SINGLE
USER
NO
YES
Slide 7
Slide 7 text
Bizarre Bugs!
Slide 8
Slide 8 text
A bizarre bug
Slide 9
Slide 9 text
More Bizarre Bugs
Slide 10
Slide 10 text
🔥🔥
Slide 11
Slide 11 text
Reminder
The bug is likely in
their code
It is a regular
contributor?
How many users
reported the bug?
SOME
MANY
A
SINGLE
USER
NO
YES
W
e’re here!
Slide 12
Slide 12 text
But What Is
Xdebug Anyway?
Slide 13
Slide 13 text
A must-have for PHP development:
➔ Step debugging
➔ Better error reporting
➔ Function calls tracing
➔ Profiling
➔ Code coverage
➔ Installed by default with Symfony Docker,
API Platform and Laravel Herd
➔ Supported by PhpStorm, VSCode and
(Neo)vim
Xdebug
Slide 14
Slide 14 text
No content
Slide 15
Slide 15 text
No content
Slide 16
Slide 16 text
Asking For Help
Slide 17
Slide 17 text
Let’s Try To Find the Issue Together!
Slide 18
Slide 18 text
Step 1:
Reproducing
Slide 19
Slide 19 text
A Minimal Reproducer
Slide 20
Slide 20 text
Step 2:
Gathering
Information
Slide 21
Slide 21 text
No content
Slide 22
Slide 22 text
➔ Debug symbols
● Make stack traces readable
● Available as extra packages for some
(but not all) distributions
○ Debian: "How To Get A Backtrace"
● Not available (yet?) for official Docker
images: docker-library/php#1538
➔ The GNU Debugger (or lldb on Mac)
Let Me Introduce You To:
Slide 23
Slide 23 text
My Reco: Compile PHP with Debug Symbols
From Source
gh repo clone php/php-src
cd php-src/
./buildconf -f
./configure \
--enable-embed \
--enable-zts \
--disable-zend-signals \
--enable-debug
make
sudo make install
Slide 24
Slide 24 text
Compile FrankenPHP to Use Our libphp
gh repo clone dunglas/frankenphp
cd frankenphp/caddy/frankenphp
export PATH="/usr/local/bin/:$PATH"
export CGO_CFLAGS=$(php-config --includes)
export CGO_LDFLAGS="$(php-config --ldflags) $(php-config --libs)"
go build
Slide 25
Slide 25 text
Compile Xdebug
gh repo clone xdebug/xdebug
cd xdebug
git checkout 3.3.1
phpize
./configure
make
#sudo make install
Slide 26
Slide 26 text
Load Xdebug
; php.ini, in the root directory of the project
zend_extension = /path/to/xdebug.so
xdebug_mode = debug
xdebug.start_with_request = yes
Slide 27
Slide 27 text
Run GDB to Gather a Stack Trace
gdb --args ./frankenphp run
# Or on Apple Silicon
lldb -- ./frankenphp run
# “run” to start or resume execution
# “bt” to show the back trace
# “break example.c:17” to set a breakpoint
# “p” to print variable values
Slide 28
Slide 28 text
No content
Slide 29
Slide 29 text
When You Can’t Use GDB…
Sometimes (e.g. in prod) you can’t install GDB.
➔ Enable verbose logs
➔ In case of segfault, enable core dumps:
ulimit -S -c unlimited
➔ lsof: list open files and network
sockets
➔ strace: list system calls (I/O…)
➔ top / htop: inspect CPU and memory
usage
➔ …
Slide 30
Slide 30 text
Step 3:
Doing Our
Research
Slide 31
Slide 31 text
➔ Symfony Docker and Laravel Octane uses
FrankenPHP
➔ FrankenPHP uses POSIX threads and
GoRoutines (GoRoutines also use threads)
➔ Using threads requires a thread-safe (ZTS)
build of PHP and of PHP extensions
➔ PHP extensions must be compatible with
non-thread-safe (NTS) and thread-safe
(ZTS) builds of PHP
Some Context