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()
|
void BackendConnection::teardownChild()
|
||||||
{
|
{
|
||||||
if (!m_child) return;
|
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) {
|
if (m_child->state() != QProcess::NotRunning) {
|
||||||
m_child->terminate();
|
m_child->terminate();
|
||||||
if (!m_child->waitForFinished(2000)) {
|
if (!m_child->waitForFinished(2000)) {
|
||||||
@@ -387,7 +395,6 @@ void BackendConnection::teardownChild()
|
|||||||
m_child->waitForFinished(1000);
|
m_child->waitForFinished(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
disconnect(m_child, nullptr, this, nullptr);
|
|
||||||
m_child->deleteLater();
|
m_child->deleteLater();
|
||||||
m_child = nullptr;
|
m_child = nullptr;
|
||||||
m_childLogBuffer.clear();
|
m_childLogBuffer.clear();
|
||||||
|
|||||||
Reference in New Issue
Block a user