bundled: disconnect child signals before terminate() to prevent restart-during-shutdown
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>
This commit is contained in:
@@ -380,6 +380,14 @@ bool BackendConnection::spawnChild(QString* errorOut)
|
||||
void BackendConnection::teardownChild()
|
||||
{
|
||||
if (!m_child) return;
|
||||
// Disconnect *before* terminating: waitForFinished() pumps a local event
|
||||
// loop, so QProcess::finished would fire synchronously inside that wait,
|
||||
// run onChildFinished as the crash-supervisor restart path, and spawn a
|
||||
// brand-new frankenphp child during shutdown — the new QProcess then
|
||||
// gets destroyed mid-spawn during stack unwinding and Qt warns
|
||||
// "Destroyed while process is still running". Severing signals first
|
||||
// turns terminate() into the synchronous reap it should always have been.
|
||||
disconnect(m_child, nullptr, this, nullptr);
|
||||
if (m_child->state() != QProcess::NotRunning) {
|
||||
m_child->terminate();
|
||||
if (!m_child->waitForFinished(2000)) {
|
||||
@@ -387,7 +395,6 @@ void BackendConnection::teardownChild()
|
||||
m_child->waitForFinished(1000);
|
||||
}
|
||||
}
|
||||
disconnect(m_child, nullptr, this, nullptr);
|
||||
m_child->deleteLater();
|
||||
m_child = nullptr;
|
||||
m_childLogBuffer.clear();
|
||||
|
||||
Reference in New Issue
Block a user