From a113dbbda81bc704105aae969f3f30616aee5878 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 5 Aug 2026 15:02:05 +0100 Subject: [PATCH] Detect crashes during python extension loads and offer to disable --- qrenderdoc/Code/CaptureContext.cpp | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/qrenderdoc/Code/CaptureContext.cpp b/qrenderdoc/Code/CaptureContext.cpp index b18eb717d..f0f80c1f7 100644 --- a/qrenderdoc/Code/CaptureContext.cpp +++ b/qrenderdoc/Code/CaptureContext.cpp @@ -229,6 +229,70 @@ CaptureContext::CaptureContext(PersistentConfig &cfg) : m_Config(cfg) rdcarray exts = CaptureContext::GetInstalledExtensions(); + { + QDir sentinelSearch(ConfigFilePath(QString())); + + bool questioned = false; + + for(QString child : sentinelSearch.entryList(QStringList() << lit("python_load*.sentinel"), + QDir::Files | QDir::NoDotAndDotDot)) + { + QFileInfo finfo(ConfigFilePath(child)); + + // to avoid this being racey, we only care if we see a sentinel that's over 10 seconds old. + // This means if two instances are starting up and both enter this section the second one + // won't detect the temporary sentinel of the first as a crash + if(finfo.exists() && finfo.lastModified().secsTo(QDateTime::currentDateTime()) > 10) + { + QFile f(ConfigFilePath(child)); + + if(questioned) + { + f.remove(); + continue; + } + + if(f.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QString extNames = QString::fromUtf8(f.readAll()); + + QMessageBox::StandardButton res = RDDialog::question( + NULL, tr("Possible python crash detected"), + tr("A previous instance of RenderDoc crashed while loading python extensions.\n\n" + "These extensions were enabled:\n%1\n" + "Would you like to disable python extensions?") + .arg(extNames)); + + questioned = true; + + if(res == QMessageBox::Yes) + { + cfg.AlwaysLoad_Extensions.clear(); + cfg.Save(); + } + } + + f.remove(); + } + } + } + + QString sentinelFilename = + ConfigFilePath(lit("python_load%1.sentinel").arg(QCoreApplication::applicationPid())); + + // create a sentinel with the list of extensions we're loading + { + QFile f(sentinelFilename); + + if(f.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QTextStream stream(&f); + + for(rdcstr ext : cfg.AlwaysLoad_Extensions) + stream << ext << lit("\n"); + } + } + for(const ExtensionMetadata &e : exts) { if(cfg.AlwaysLoad_Extensions.contains(e.package)) @@ -237,6 +301,12 @@ CaptureContext::CaptureContext(PersistentConfig &cfg) : m_Config(cfg) LoadExtension(e.package); } } + + // remove our sentinel now + { + QFile f(sentinelFilename); + f.remove(); + } } CaptureContext::~CaptureContext()