teardownChild called terminate() then waitForFinished(2000), then
disconnected the QProcess signals. But waitForFinished pumps a local
event loop — when frankenphp exited inside that wait, QProcess::finished
fired synchronously, ran onChildFinished as the crash-supervisor's
restart path, and spawned a brand-new frankenphp child during
shutdown. That child's QProcess was then destroyed mid-spawn during
stack unwinding, producing the "QProcess: Destroyed while process is
still running" warning the bundled-supervisor.sh test catches.
Fix: disconnect first, then terminate. Severing signals before the
wait turns terminate() into the synchronous reap it should always
have been; onChildFinished can't run for a process we're explicitly
tearing down.
Local integration test passes clean — both the cache-baked-mount-path
relaunch and the graceful-shutdown assertion go through without the
warning or any orphan frankenphp.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>