Luther Monson, Staff Software Engineer at SUSE

Luther Monson

Go by way of PHP · Containers · VMs · Windows · Kubernetes

Building a Custom SAPI - How PHP Actually Talks to the Outside World

php-fpm, mod_php and the PHP command line all plug into PHP the same way. Here's how ePHPm does it, and the shortcut that broke WordPress.

9-Minute Read

Table mapping PHP operations like echo, header(), $_POST, $_COOKIE and $_SERVER to SAPI callbacks and to the Rust side of ePHPm

If you’ve only ever run PHP behind nginx, you’ve probably never had to think about how echo reaches a socket. When you embed PHP like ePHPm does, it’s the first thing you have to answer. The answer is a SAPI. There is very little written about implementing one. Most of what I know came from reading sapi/cli, sapi/cgi and sapi/embed in php-src. Then I found out which parts I’d misread. This is the write-up I wanted back in March.

Fixing Windows Archive Extraction in SPC

"The pipe has been ended" wasn't a pipe problem. It was the wrong tar program and Windows symlinks, and fixing one line of static-php-cli took three tries.

7-Minute Read

Diagram: 7za decompressing into a pipe read by MinGW tar, which exits on a C:\ path and leaves 7za reporting The pipe has been ended

One of the first things that broke when I started building PHP on Windows with static-php-cli (SPC) wasn’t PHP at all. It was unpacking the source tarballs. libxml2, xz and a couple of others would die partway through extraction with:

The Pragmatism of ePHPm - Every Decision Has a "Because" Behind It

ePHPm hit v0.1.0 this week. It isn't a rewrite-it-in-Rust project. Here's what I built, what I borrowed, what I sent upstream, and what I deliberately haven't built.

7-Minute Read

ePHPm in the center with six boxes: Rust and C wrapper, KV store, chitchat gossip, static-php-cli upstream fixes, litewire, and a dashed box of features not built yet

ePHPm tagged v0.1.0 this week, three months after the first commit. Before the feature list grows any further I want to write down how decisions get made on it. This is mostly for myself. The easiest way to ruin a project like this is to let it turn into a checklist of things other projects have.

PHP Signal Safety - The Init Ordering Bug Nobody Warns You About

Embedding PHP in a multithreaded server means PHP's timeout signals can land on any thread. How ePHPm got that under control.

11-Minute Read

Thread timeline: the main thread installs PHP's signal handlers during php_embed_init, a PHP thread later arms ITIMER_PROF, and SIGPROF is delivered to a tokio worker that has no PHP state

Last week I wrote about why ePHPm embeds PHP from Rust and promised the signal bug its own post. Here it is. It’s the kind of bug where the fix is about ten lines and the explanation is the whole post. Nothing in PHP’s embed documentation (there’s barely any) tells you that initializing PHP has process-wide side effects. Those side effects assume PHP is the only thing in the process.

Why Rust for PHP Embedding (Not Go)

I'm a Go developer building a PHP application server in Rust. Here's the FFI reasoning, the C wrapper it forced on me, and what cgo actually costs when you measure it.

11-Minute Read

Diagram of a request flowing from hyper/tokio through a Rust blocking thread, a C wrapper with setjmp, and libphp, with SAPI callbacks writing into thread-local C buffers

Go is my primary language and has been for a long time. When I started building ePHPm a few weeks ago the obvious move was to write it in Go. ePHPm is a PHP application server. It’s one binary that embeds the real PHP interpreter (libphp, the Zend engine) and puts an HTTP server, TLS, a KV cache and a database proxy around it. A PHP app doesn’t need nginx + php-fpm + Redis to run. FrankenPHP already proved the “PHP inside a Go web server” idea works, and it works well. I…

Recent Posts

Categories

About

Luther is a 20+ year software veteran specializing in backend APIs and architecting products. Employed at SUSE as the Team Lead for the Containers on Windows Team working on Rancher + Kubernetes