forked from quickshell/quickshell
core/reloader: fix more crashes (not all of them)
This commit is contained in:
parent
31462b9797
commit
c6e5a35745
|
@ -26,27 +26,46 @@ static QHash<QQmlEngine*, EngineGeneration*> g_generations; // NOLINT
|
||||||
|
|
||||||
EngineGeneration::EngineGeneration(QmlScanner scanner)
|
EngineGeneration::EngineGeneration(QmlScanner scanner)
|
||||||
: scanner(std::move(scanner))
|
: scanner(std::move(scanner))
|
||||||
, interceptNetFactory(this->scanner.qmldirIntercepts) {
|
, interceptNetFactory(this->scanner.qmldirIntercepts)
|
||||||
g_generations.insert(&this->engine, this);
|
, engine(new QQmlEngine()) {
|
||||||
|
g_generations.insert(this->engine, this);
|
||||||
|
|
||||||
this->engine.addUrlInterceptor(&this->urlInterceptor);
|
this->engine->addUrlInterceptor(&this->urlInterceptor);
|
||||||
this->engine.setNetworkAccessManagerFactory(&this->interceptNetFactory);
|
this->engine->setNetworkAccessManagerFactory(&this->interceptNetFactory);
|
||||||
this->engine.setIncubationController(&this->delayedIncubationController);
|
this->engine->setIncubationController(&this->delayedIncubationController);
|
||||||
|
|
||||||
this->engine.addImageProvider("icon", new IconImageProvider());
|
this->engine->addImageProvider("icon", new IconImageProvider());
|
||||||
|
|
||||||
QuickshellPlugin::runConstructGeneration(*this);
|
QuickshellPlugin::runConstructGeneration(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineGeneration::~EngineGeneration() {
|
EngineGeneration::~EngineGeneration() {
|
||||||
g_generations.remove(&this->engine);
|
g_generations.remove(this->engine);
|
||||||
if (this->root != nullptr) this->root->deleteLater();
|
delete this->engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EngineGeneration::destroy() {
|
void EngineGeneration::destroy() {
|
||||||
if (this->root != nullptr) {
|
// Multiple generations can detect a reload at the same time.
|
||||||
|
delete this->watcher;
|
||||||
|
this->watcher = nullptr;
|
||||||
|
|
||||||
|
// Yes all of this is actually necessary.
|
||||||
|
if (this->engine != nullptr && this->root != nullptr) {
|
||||||
QObject::connect(this->root, &QObject::destroyed, this, [this]() {
|
QObject::connect(this->root, &QObject::destroyed, this, [this]() {
|
||||||
delete this;
|
// The timer seems to fix *one* of the possible qml item destructor crashes.
|
||||||
|
QTimer::singleShot(0, [this]() {
|
||||||
|
// Garbage is not collected during engine destruction.
|
||||||
|
this->engine->collectGarbage();
|
||||||
|
|
||||||
|
QObject::connect(this->engine, &QObject::destroyed, this, [this]() { delete this; });
|
||||||
|
|
||||||
|
// Even after all of that there's still multiple failing assertions and segfaults.
|
||||||
|
// Pray you don't hit one.
|
||||||
|
// Note: it appeats *some* of the crashes are related to values owned by the generation.
|
||||||
|
// Test by commenting the connect() above.
|
||||||
|
this->engine->deleteLater();
|
||||||
|
this->engine = nullptr;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this->root->deleteLater();
|
this->root->deleteLater();
|
||||||
|
@ -63,8 +82,8 @@ void EngineGeneration::onReload(EngineGeneration* old) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* app = QCoreApplication::instance();
|
auto* app = QCoreApplication::instance();
|
||||||
QObject::connect(&this->engine, &QQmlEngine::quit, app, &QCoreApplication::quit);
|
QObject::connect(this->engine, &QQmlEngine::quit, app, &QCoreApplication::quit);
|
||||||
QObject::connect(&this->engine, &QQmlEngine::exit, app, &QCoreApplication::exit);
|
QObject::connect(this->engine, &QQmlEngine::exit, app, &QCoreApplication::exit);
|
||||||
|
|
||||||
this->root->reload(old == nullptr ? nullptr : old->root);
|
this->root->reload(old == nullptr ? nullptr : old->root);
|
||||||
this->singletonRegistry.onReload(old == nullptr ? nullptr : &old->singletonRegistry);
|
this->singletonRegistry.onReload(old == nullptr ? nullptr : &old->singletonRegistry);
|
||||||
|
@ -72,14 +91,17 @@ void EngineGeneration::onReload(EngineGeneration* old) {
|
||||||
emit this->reloadFinished();
|
emit this->reloadFinished();
|
||||||
|
|
||||||
if (old != nullptr) {
|
if (old != nullptr) {
|
||||||
old->destroy();
|
|
||||||
QObject::connect(old, &QObject::destroyed, this, [this]() { this->postReload(); });
|
QObject::connect(old, &QObject::destroyed, this, [this]() { this->postReload(); });
|
||||||
|
old->destroy();
|
||||||
} else {
|
} else {
|
||||||
this->postReload();
|
this->postReload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EngineGeneration::postReload() {
|
void EngineGeneration::postReload() {
|
||||||
|
// This can be called on a generation during its destruction.
|
||||||
|
if (this->engine == nullptr || this->root == nullptr) return;
|
||||||
|
|
||||||
QuickshellPlugin::runOnReload();
|
QuickshellPlugin::runOnReload();
|
||||||
PostReloadHook::postReloadTree(this->root);
|
PostReloadHook::postReloadTree(this->root);
|
||||||
this->singletonRegistry.onPostReload();
|
this->singletonRegistry.onPostReload();
|
||||||
|
@ -132,7 +154,10 @@ void EngineGeneration::registerIncubationController(QQmlIncubationController* co
|
||||||
|
|
||||||
qCDebug(logIncubator) << "Registered incubation controller" << controller;
|
qCDebug(logIncubator) << "Registered incubation controller" << controller;
|
||||||
|
|
||||||
if (this->engine.incubationController() == &this->delayedIncubationController) {
|
// This function can run during destruction.
|
||||||
|
if (this->engine == nullptr) return;
|
||||||
|
|
||||||
|
if (this->engine->incubationController() == &this->delayedIncubationController) {
|
||||||
this->assignIncubationController();
|
this->assignIncubationController();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -156,7 +181,10 @@ void EngineGeneration::deregisterIncubationController(QQmlIncubationController*
|
||||||
qCDebug(logIncubator) << "Deregistered incubation controller" << controller;
|
qCDebug(logIncubator) << "Deregistered incubation controller" << controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->engine.incubationController() == controller) {
|
// This function can run during destruction.
|
||||||
|
if (this->engine == nullptr) return;
|
||||||
|
|
||||||
|
if (this->engine->incubationController() == controller) {
|
||||||
qCDebug(logIncubator
|
qCDebug(logIncubator
|
||||||
) << "Destroyed incubation controller was currently active, reassigning from pool";
|
) << "Destroyed incubation controller was currently active, reassigning from pool";
|
||||||
this->assignIncubationController();
|
this->assignIncubationController();
|
||||||
|
@ -183,7 +211,10 @@ void EngineGeneration::incubationControllerDestroyed() {
|
||||||
qCDebug(logIncubator) << "Destroyed incubation controller" << controller << "deregistered";
|
qCDebug(logIncubator) << "Destroyed incubation controller" << controller << "deregistered";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->engine.incubationController() == controller) {
|
// This function can run during destruction.
|
||||||
|
if (this->engine == nullptr) return;
|
||||||
|
|
||||||
|
if (this->engine->incubationController() == controller) {
|
||||||
qCDebug(logIncubator
|
qCDebug(logIncubator
|
||||||
) << "Destroyed incubation controller was currently active, reassigning from pool";
|
) << "Destroyed incubation controller was currently active, reassigning from pool";
|
||||||
this->assignIncubationController();
|
this->assignIncubationController();
|
||||||
|
@ -198,7 +229,7 @@ void EngineGeneration::assignIncubationController() {
|
||||||
qCDebug(logIncubator) << "Assigning incubation controller to engine:" << controller
|
qCDebug(logIncubator) << "Assigning incubation controller to engine:" << controller
|
||||||
<< "fallback:" << (controller == &this->delayedIncubationController);
|
<< "fallback:" << (controller == &this->delayedIncubationController);
|
||||||
|
|
||||||
this->engine.setIncubationController(controller);
|
this->engine->setIncubationController(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
EngineGeneration* EngineGeneration::findObjectGeneration(QObject* object) {
|
EngineGeneration* EngineGeneration::findObjectGeneration(QObject* object) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
QmlScanner scanner;
|
QmlScanner scanner;
|
||||||
QsUrlInterceptor urlInterceptor;
|
QsUrlInterceptor urlInterceptor;
|
||||||
QsInterceptNetworkAccessManagerFactory interceptNetFactory;
|
QsInterceptNetworkAccessManagerFactory interceptNetFactory;
|
||||||
QQmlEngine engine;
|
QQmlEngine* engine = nullptr;
|
||||||
ShellRoot* root = nullptr;
|
ShellRoot* root = nullptr;
|
||||||
SingletonRegistry singletonRegistry;
|
SingletonRegistry singletonRegistry;
|
||||||
QFileSystemWatcher* watcher = nullptr;
|
QFileSystemWatcher* watcher = nullptr;
|
||||||
|
|
|
@ -58,9 +58,9 @@ void RootWrapper::reloadGraph(bool hard) {
|
||||||
auto url = QUrl::fromLocalFile(this->rootPath);
|
auto url = QUrl::fromLocalFile(this->rootPath);
|
||||||
// unless the original file comes from the qsintercept scheme
|
// unless the original file comes from the qsintercept scheme
|
||||||
url.setScheme("qsintercept");
|
url.setScheme("qsintercept");
|
||||||
auto component = QQmlComponent(&generation->engine, url);
|
auto component = QQmlComponent(generation->engine, url);
|
||||||
|
|
||||||
auto* obj = component.beginCreate(generation->engine.rootContext());
|
auto* obj = component.beginCreate(generation->engine->rootContext());
|
||||||
|
|
||||||
if (obj == nullptr) {
|
if (obj == nullptr) {
|
||||||
qWarning() << component.errorString().toStdString().c_str();
|
qWarning() << component.errorString().toStdString().c_str();
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace {
|
||||||
|
|
||||||
class SniPlugin: public QuickshellPlugin {
|
class SniPlugin: public QuickshellPlugin {
|
||||||
void constructGeneration(EngineGeneration& generation) override {
|
void constructGeneration(EngineGeneration& generation) override {
|
||||||
generation.engine.addImageProvider("service.sni", new qs::service::sni::TrayImageProvider());
|
generation.engine->addImageProvider("service.sni", new qs::service::sni::TrayImageProvider());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue