Skip to content

FrankenPHP v1.12.0: HTTP server never starts - hangs in initPHPThreads/WaitFor (non-worker mode) #2250

@cmeyerdierks

Description

@cmeyerdierks

What happened?

FrankenPHP v1.12.0: HTTP server never starts - hangs in initPHPThreads/WaitFor (non-worker mode)

Description

After upgrading from FrankenPHP v1.11.3 to v1.12.0, the HTTP server never starts.
The process hangs indefinitely in initPHPThreads -> phpMainThread.start() -> ThreadState.WaitFor().
The Caddy admin API (port 2019) starts successfully, but the HTTP listener (port 8000) never binds.

Environment

  • FrankenPHP v1.12.0 (PHP 8.4.18, Caddy v2.11.2)
  • Docker: ghcr.io/shopware/docker-base:8.4-frankenphp
  • Linux amd64, 12 CPU cores, ~22GB RAM
  • Non-worker mode (no FRANKENPHP_CONFIG set)
  • Reproducible on every container restart

Expected behavior

FrankenPHP starts and binds HTTP listener on port 8000.

Actual behavior

Process hangs after admin API starts. Goroutine dump shows:

goroutine 1 [chan receive, 23 minutes]:
  state.(*ThreadState).WaitFor()     <- blocked for 23 minutes
    /go/src/app/internal/state/state.go:159
  frankenphp.(*phpMainThread).start()
    /go/src/app/phpmainthread.go:108
  frankenphp.initPHPThreads(0x18, 0x18, 0x0)   <- 24 threads, 0 workers
    /go/src/app/phpmainthread.go:53
  frankenphp.Init()
    /go/src/app/frankenphp.go:312
  caddy.(*FrankenPHPApp).Start()
    /go/src/app/caddy/app.go:171

Two additional goroutines are stuck in [syscall, 23 minutes, locked to thread].

Container logs

Startup stops here - no "server running" message ever appears:

{"logger":"admin","msg":"admin endpoint started","address":"localhost:2019"}
{"logger":"pki.ca.local","msg":"root certificate trust store installation disabled"}
{"logger":"tls.cache.maintenance","msg":"started background certificate maintenance"}
// <- hangs here, never reaches HTTP server start

Full goroutine dump

goroutine 32 [running]:
runtime/pprof.writeGoroutineStacks({0x758c3a796928, 0x12a96096c048})
	/usr/local/go/src/runtime/pprof/pprof.go:819 +0x6b
runtime/pprof.writeGoroutine({0x758c3a796928?, 0x12a96096c048?}, 0x4?)
	/usr/local/go/src/runtime/pprof/pprof.go:782 +0x25
runtime/pprof.(*Profile).WriteTo(0x3589530?, {0x758c3a796928?, 0x12a96096c048?}, 0xc?)
	/usr/local/go/src/runtime/pprof/pprof.go:408 +0x149
net/http/pprof.handler.ServeHTTP({0x12a960b3c191, 0x9}, {0x22cbe10, 0x12a96096c048}, 0x12a960bda140)
	/usr/local/go/src/net/http/pprof/pprof.go:273 +0x52a
net/http/pprof.Index({0x22cbe10, 0x12a96096c048}, 0x12a960bda140?)
	/usr/local/go/src/net/http/pprof/pprof.go:397 +0xda

goroutine 1 [chan receive, 23 minutes]:
github.com/dunglas/frankenphp/internal/state.(*ThreadState).WaitFor(0x12a960a065c0, {0x12a9606c5268, 0x1, 0x1})
	/go/src/app/internal/state/state.go:159 +0x158
github.com/dunglas/frankenphp.(*phpMainThread).start(0x12a960bb98c0)
	/go/src/app/phpmainthread.go:108 +0x77
github.com/dunglas/frankenphp.initPHPThreads(0x18, 0x18, 0x0)
	/go/src/app/phpmainthread.go:53 +0x1ae
github.com/dunglas/frankenphp.Init({0x12a9609c4310, 0x8, 0x0?})
	/go/src/app/frankenphp.go:312 +0x3fa
github.com/dunglas/frankenphp/caddy.(*FrankenPHPApp).Start(0x12a9608dc800)
	/go/src/app/caddy/app.go:171 +0xc4c
github.com/caddyserver/caddy/v2.run.func2(...)
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/caddy.go:455
github.com/caddyserver/caddy/v2.run(0x229efa8?, 0x1)
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/caddy.go:471 +0x542
github.com/caddyserver/caddy/v2.unsyncedDecodeAndRun({0x12a960cb2c00, 0x59d, 0x600}, 0x1)
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/caddy.go:364 +0x17a
github.com/caddyserver/caddy/v2.changeConfig({0x1f9bf3e, 0x4}, {0x1fa1f0f, 0x7}, {0x12a960cb2600, 0x59d, 0x600}, {0x0, 0x0}, 0x1)
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/caddy.go:248 +0x959
github.com/caddyserver/caddy/v2.Load({0x12a960cb2600, 0x59d, 0x600}, 0x1)
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/caddy.go:137 +0x225
github.com/caddyserver/caddy/v2/cmd.cmdRun({0x0?})
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/cmd/commandfuncs.go:267 +0x872
github.com/caddyserver/caddy/v2/cmd.init.1.func2.WrapCommandFuncForCobra.1(0x12a960c2d208, {0x1f9bfea?, 0x4?, 0x1f9bf76?})
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/cmd/cobra.go:151 +0x2f
github.com/spf13/cobra.(*Command).execute(0x12a960c2d208, {0x12a9609278c0, 0x4, 0x4})
	/root/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1015 +0xb14
github.com/spf13/cobra.(*Command).ExecuteC(0x12a960c2cc08)
	/root/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1148 +0x465
github.com/spf13/cobra.(*Command).Execute(...)
	/root/go/pkg/mod/github.com/spf13/cobra@v1.10.2/command.go:1071
github.com/caddyserver/caddy/v2/cmd.Main()
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/cmd/main.go:72 +0x65
main.main()
	/go/src/app/caddy/frankenphp/main.go:14 +0xf

goroutine 17 [syscall, 23 minutes, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1771 +0x1

goroutine 82 [syscall, 23 minutes, locked to thread]:
runtime.goexit({})
	/usr/local/go/src/runtime/asm_amd64.s:1771 +0x1

goroutine 67 [sync.RWMutex.RLock, 3 minutes]:
sync.runtime_SemacquireRWMutexR(0x758c99e44be0?, 0x18?, 0x12a960665808?)
	/usr/local/go/src/runtime/sema.go:100 +0x25
sync.(*RWMutex).RLock(...)
	/usr/local/go/src/sync/rwmutex.go:74
github.com/caddyserver/caddy/v2.readConfig({0x12a96060c304, 0x8}, {0x22b4aa0, 0x12a960c00060})
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/caddy.go:282 +0x85
github.com/caddyserver/caddy/v2.handleConfig({0x22cbe10, 0x12a960c00048}, 0x12a960e94000)
	/root/go/pkg/mod/github.com/caddyserver/caddy/v2@v2.11.2/admin.go:1029 +0xc29

Reproduction

  1. Use ghcr.io/shopware/docker-base:8.4-frankenphp (contains v1.12.0 as of 2026-03-07)
  2. Use default Caddyfile listening on :8000 with php directive
  3. No worker mode configured (FRANKENPHP_CONFIG empty)
  4. Start container -> HTTP server never binds

Caddyfile

{
	skip_install_trust
	{$CADDY_GLOBAL_OPTIONS}
	frankenphp {
		{$FRANKENPHP_CONFIG}
	}
}

{$CADDY_EXTRA_CONFIG}

:8000 {
	root * /var/www/html/public
	encode zstd gzip
	log

	handle {
		@phpRoute {
			not path /theme/* /media/* /thumbnail/* /bundles/*
			not file {path}
		}
		rewrite @phpRoute index.php
		@frontController path index.php
		php @frontController
		file_server {
			hide *.php
		}
	}
}

Workaround

Pinning to FrankenPHP v1.11.3 via Docker image digest resolves the issue:

FROM ghcr.io/shopware/docker-base:8.4-frankenphp@sha256:0c08cb4f0e76b841b1e7973cb257d01f85121f49dcc8c5086d85f9cd71f738ea AS base-image

Additional notes

  • php -v works fine inside the container (CLI SAPI is OK)
  • Running frankenphp run manually via docker exec (as a 2nd instance alongside the hung PID 1) sometimes succeeds and shows "server running"
  • A stale Caddy lock file (/data/caddy/locks/storage_clean.lock) was observed; removing it + restart temporarily fixed the issue once, but the hang returned on subsequent restarts
  • GOMAXPROCS=12, so FrankenPHP creates 24 threads (2x GOMAXPROCS)
  • The goroutine dump was obtained via: curl -s http://localhost:2019/debug/pprof/goroutine?debug=2
  • v1.11.3 with the same Caddyfile and configuration works flawlessly

Build Type

Docker (Debian Trixie)

Worker Mode

No

Operating System

GNU/Linux

CPU Architecture

x86_64

PHP configuration

phpinfo()
PHP Version => 8.4.17

System => Linux 10c5a178951f 6.8.0-101-generic #101-Ubuntu SMP PREEMPT_DYNAMIC Mon Feb  9 10:15:05 UTC 2026 x86_64
Build Date => Feb  3 2026 02:32:34
Build System => Linux - Docker
Build Provider => https://github.com/docker-library/php
Configure Command =>  './configure'  '--build=x86_64-linux-gnu' '--sysconfdir=/usr/local/etc' '--with-config-file-path=/usr/local/etc/php' '--with-config-file-scan-dir=/usr/local/etc/php/conf.d' '--enable-option-checking=fatal' '--with-mhash' '--with-pic' '--enable-mbstring' '--enable-mysqlnd' '--with-password-argon2' '--with-sodium=shared' '--with-pdo-sqlite=/usr' '--with-sqlite3=/usr' '--with-curl' '--with-iconv' '--with-openssl' '--with-readline' '--with-zlib' '--enable-phpdbg' '--enable-phpdbg-readline' '--with-pear' '--with-libdir=lib/x86_64-linux-gnu' '--enable-embed' '--enable-zts' '--disable-zend-signals' 'build_alias=x86_64-linux-gnu' 'PHP_UNAME=Linux - Docker' 'PHP_BUILD_PROVIDER=https://github.com/docker-library/php'
Server API => Command Line Interface
Virtual Directory Support => enabled
Configuration File (php.ini) Path => /usr/local/etc/php
Loaded Configuration File => (none)
Scan this dir for additional .ini files => /usr/local/etc/php/conf.d
Additional .ini files parsed => /usr/local/etc/php/conf.d/docker-php-ext-amqp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-apcu.ini,
/usr/local/etc/php/conf.d/docker-php-ext-bcmath.ini,
/usr/local/etc/php/conf.d/docker-php-ext-bz2.ini,
/usr/local/etc/php/conf.d/docker-php-ext-ffi.ini,
/usr/local/etc/php/conf.d/docker-php-ext-ftp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gd.ini,
/usr/local/etc/php/conf.d/docker-php-ext-gmp.ini,
/usr/local/etc/php/conf.d/docker-php-ext-intl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-mysqli.ini,
/usr/local/etc/php/conf.d/docker-php-ext-opcache.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pcntl.ini,
/usr/local/etc/php/conf.d/docker-php-ext-pdo_mysql.ini,
/usr/local/etc/php/conf.d/docker-php-ext-redis.ini,
/usr/local/etc/php/conf.d/docker-php-ext-soap.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sockets.ini,
/usr/local/etc/php/conf.d/docker-php-ext-sodium.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zip.ini,
/usr/local/etc/php/conf.d/docker-php-ext-zstd.ini,
/usr/local/etc/php/conf.d/docker.ini,
/usr/local/etc/php/conf.d/timezone.ini

PHP API => 20240924
PHP Extension => 20240924
Zend Extension => 420240924
Zend Extension Build => API420240924,TS
PHP Extension Build => API20240924,TS
PHP Integer Size => 64 bits
Debug Build => no
Thread Safety => enabled
Thread API => POSIX Threads
Zend Signal Handling => disabled
Zend Memory Manager => enabled
Zend Multibyte Support => provided by mbstring
Zend Max Execution Timers => enabled
IPv6 Support => enabled
DTrace Support => disabled

Registered PHP Streams => https, ftps, compress.zlib, compress.bzip2, php, file, glob, data, http, ftp, phar, zip, compress.zstd
Registered Stream Socket Transports => tcp, udp, unix, udg, ssl, tls, tlsv1.0, tlsv1.1, tlsv1.2, tlsv1.3
Registered Stream Filters => zlib.*, convert.iconv.*, bzip2.*, string.rot13, string.toupper, string.tolower, convert.*, consumed, dechunk

This program makes use of the Zend Scripting Language Engine:
Zend Engine v4.4.17, Copyright (c) Zend Technologies
    with Zend OPcache v8.4.17, Copyright (c), by Zend Technologies

 _______________________________________________________________________

Configuration

amqp

Version => 2.2.0dev
Compiled => Feb 15 2026 @ 04:51:49
AMQP protocol version => 0-9-1
librabbitmq version => 0.15.0
Default max channels per connection => 256
Default max frame size => 131072
Default heartbeats interval => 0

Directive => Local Value => Master Value
amqp.auto_ack => 0 => 0
amqp.cacert => no value => no value
amqp.cert => no value => no value
amqp.channel_max => 256 => 256
amqp.connect_timeout => 0 => 0
amqp.deserialization_depth => 128 => 128
amqp.frame_max => 131072 => 131072
amqp.global_prefetch_count => 0 => 0
amqp.global_prefetch_size => 0 => 0
amqp.heartbeat => 0 => 0
amqp.host => localhost => localhost
amqp.key => no value => no value
amqp.login => guest => guest
amqp.password => guest => guest
amqp.port => 5672 => 5672
amqp.prefetch_count => 3 => 3
amqp.prefetch_size => 0 => 0
amqp.read_timeout => 0 => 0
amqp.rpc_timeout => 0 => 0
amqp.sasl_method => AMQP_SASL_METHOD_PLAIN => AMQP_SASL_METHOD_PLAIN
amqp.serialization_depth => 128 => 128
amqp.timeout => no value => no value
amqp.verify => 1 => 1
amqp.vhost => / => /
amqp.write_timeout => 0 => 0

apcu

APCu Support => Disabled
Version => 5.1.28
APCu Debugging => Disabled
MMAP Support => Enabled
MMAP File Mask =>
Serialization Support => Disabled
Build Date => Feb 15 2026 04:50:07

Directive => Local Value => Master Value
apc.coredump_unmap => Off => Off
apc.enable_cli => Off => Off
apc.enabled => On => On
apc.entries_hint => 0 => 0
apc.gc_ttl => 3600 => 3600
apc.mmap_file_mask => no value => no value
apc.mmap_hugepage_size => 0 => 0
apc.preload_path => no value => no value
apc.serializer => php => php
apc.shm_size => 32M => 32M
apc.slam_defense => Off => Off
apc.smart => 0 => 0
apc.ttl => 0 => 0
apc.use_request_time => Off => Off

bcmath

BCMath support => enabled

Directive => Local Value => Master Value
bcmath.scale => 0 => 0

bz2

BZip2 Support => Enabled
Stream Wrapper support => compress.bzip2://
Stream Filter support => bzip2.decompress, bzip2.compress
BZip2 Version => 1.0.8, 13-Jul-2019

Core

PHP Version => 8.4.17

Directive => Local Value => Master Value
allow_url_fopen => On => On
allow_url_include => Off => Off
arg_separator.input => & => &
arg_separator.output => & => &
auto_append_file => no value => no value
auto_globals_jit => On => On
auto_prepend_file => no value => no value
browscap => no value => no value
default_charset => UTF-8 => UTF-8
default_mimetype => text/html => text/html
disable_classes => no value => no value
disable_functions => no value => no value
display_errors => Off => Off
display_startup_errors => Off => Off
doc_root => no value => no value
docref_ext => no value => no value
docref_root => no value => no value
enable_dl => On => On
enable_post_data_reading => On => On
error_append_string => no value => no value
error_log => no value => no value
error_log_mode => 0644 => 0644
error_prepend_string => no value => no value
error_reporting => E_ALL => E_ALL
expose_php => Off => Off
extension_dir => /usr/local/lib/php/extensions/no-debug-zts-20240924 => /usr/local/lib/php/extensions/no-debug-zts-20240924
fiber.stack_size => no value => no value
file_uploads => On => On
hard_timeout => 2 => 2
highlight.comment => <span style="color: #FF8000">#FF8000</span> => <span style="color: #FF8000">#FF8000</span>
highlight.default => <span style="color: #0000BB">#0000BB</span> => <span style="color: #0000BB">#0000BB</span>
highlight.html => <span style="color: #000000">#000000</span> => <span style="color: #000000">#000000</span>
highlight.keyword => <span style="color: #007700">#007700</span> => <span style="color: #007700">#007700</span>
highlight.string => <span style="color: #DD0000">#DD0000</span> => <span style="color: #DD0000">#DD0000</span>
html_errors => Off => Off
ignore_repeated_errors => Off => Off
ignore_repeated_source => Off => Off
ignore_user_abort => Off => Off
implicit_flush => On => On
include_path => .:/usr/local/lib/php => .:/usr/local/lib/php
input_encoding => no value => no value
internal_encoding => no value => no value
log_errors => Off => Off
mail.add_x_header => Off => Off
mail.force_extra_parameters => no value => no value
mail.log => no value => no value
mail.mixed_lf_and_crlf => Off => Off
max_execution_time => 0 => 0
max_file_uploads => 20 => 20
max_input_nesting_level => 64 => 64
max_input_time => -1 => -1
max_input_vars => 1000 => 1000
max_multipart_body_parts => -1 => -1

Relevant log output

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions