[scripting] Avoid threading issues when loading from a file
Summary: KWin::Script::loadScriptFromFile ran in it's own thread and accessed member variables of KWin::Script without any guards. Potentially script could be destroyed whilst the file is loading. Rather than adding mutexes everywhere, this patch scopes the QFile object to be local to the threaded function making it independent. BUG: 403038 Test Plan: Ran a script from a file Reviewers: #kwin, graesslin Reviewed By: #kwin, graesslin Subscribers: kwin Tags: #kwin Differential Revision: https://phabricator.kde.org/D18126
This commit is contained in:
parent
fbe219172a
commit
ba7aecfe53
2 changed files with 11 additions and 14 deletions
|
@ -231,9 +231,9 @@ KWin::AbstractScript::AbstractScript(int id, QString scriptName, QString pluginN
|
|||
: QObject(parent)
|
||||
, m_scriptId(id)
|
||||
, m_pluginName(pluginName)
|
||||
, m_fileName(scriptName)
|
||||
, m_running(false)
|
||||
{
|
||||
m_scriptFile.setFileName(scriptName);
|
||||
if (m_pluginName.isNull()) {
|
||||
m_pluginName = scriptName;
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ void KWin::AbstractScript::stop()
|
|||
|
||||
void KWin::AbstractScript::printMessage(const QString &message)
|
||||
{
|
||||
qCDebug(KWIN_SCRIPTING) << scriptFile().fileName() << ":" << message;
|
||||
qCDebug(KWIN_SCRIPTING) << fileName() << ":" << message;
|
||||
emit print(message);
|
||||
}
|
||||
|
||||
|
@ -468,16 +468,16 @@ void KWin::Script::run()
|
|||
m_starting = true;
|
||||
QFutureWatcher<QByteArray> *watcher = new QFutureWatcher<QByteArray>(this);
|
||||
connect(watcher, SIGNAL(finished()), SLOT(slotScriptLoadedFromFile()));
|
||||
watcher->setFuture(QtConcurrent::run(this, &KWin::Script::loadScriptFromFile));
|
||||
watcher->setFuture(QtConcurrent::run(this, &KWin::Script::loadScriptFromFile, fileName()));
|
||||
}
|
||||
|
||||
QByteArray KWin::Script::loadScriptFromFile()
|
||||
QByteArray KWin::Script::loadScriptFromFile(const QString &fileName)
|
||||
{
|
||||
if (!scriptFile().open(QIODevice::ReadOnly)) {
|
||||
QFile file(fileName);
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
return QByteArray();
|
||||
}
|
||||
QByteArray result(scriptFile().readAll());
|
||||
scriptFile().close();
|
||||
QByteArray result(file.readAll());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -591,7 +591,7 @@ void KWin::DeclarativeScript::run()
|
|||
return;
|
||||
}
|
||||
|
||||
m_component->loadUrl(QUrl::fromLocalFile(scriptFile().fileName()));
|
||||
m_component->loadUrl(QUrl::fromLocalFile(fileName()));
|
||||
if (m_component->isLoading()) {
|
||||
connect(m_component, &QQmlComponent::statusChanged, this, &DeclarativeScript::createComponent);
|
||||
} else {
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
AbstractScript(int id, QString scriptName, QString pluginName, QObject *parent = nullptr);
|
||||
~AbstractScript();
|
||||
QString fileName() const {
|
||||
return m_scriptFile.fileName();
|
||||
return m_fileName;
|
||||
}
|
||||
const QString &pluginName() {
|
||||
return m_pluginName;
|
||||
|
@ -153,9 +153,6 @@ Q_SIGNALS:
|
|||
void runningChanged(bool);
|
||||
|
||||
protected:
|
||||
QFile &scriptFile() {
|
||||
return m_scriptFile;
|
||||
}
|
||||
bool running() const {
|
||||
return m_running;
|
||||
}
|
||||
|
@ -204,7 +201,7 @@ private:
|
|||
**/
|
||||
QAction *createMenu(const QString &title, QScriptValue &items, QMenu *parent);
|
||||
int m_scriptId;
|
||||
QFile m_scriptFile;
|
||||
QString m_fileName;
|
||||
QString m_pluginName;
|
||||
bool m_running;
|
||||
QHash<QAction*, QScriptValue> m_shortcutCallbacks;
|
||||
|
@ -255,7 +252,7 @@ private:
|
|||
* Read the script from file into a byte array.
|
||||
* If file cannot be read an empty byte array is returned.
|
||||
**/
|
||||
QByteArray loadScriptFromFile();
|
||||
QByteArray loadScriptFromFile(const QString &fileName);
|
||||
QScriptEngine *m_engine;
|
||||
bool m_starting;
|
||||
QScopedPointer<ScriptUnloaderAgent> m_agent;
|
||||
|
|
Loading…
Reference in a new issue