diff options
author | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2017-09-28 14:31:17 +0200 |
---|---|---|
committer | Holger Freyther <holger+qt@freyther.de> | 2017-11-09 13:03:47 +0000 |
commit | e5047dc19d84dc45eef92c2c59bab52637f092d6 (patch) | |
tree | 7c328ba315806add1e0926d07d286e72d7cd4db1 /wayland | |
parent | a84980d2cde1f62e574446729d48dd0b29804933 (diff) |
processlauncher: Fix crashing on destruction with running apps
The democompositor would crash because the QProcess will be deleted
from within ~QObject and then emit a signal which will access the
partially destructed WaylandProcessLauncher. Iterate through the
list and disconnect the slots and then delete the QProcess before
the ~QObject is ran.
An alternative would be to iterate the m_appStates and just block
the signals of the QProcess. This might be more future proof (e.g.
another signal being connected) but can impact other signal/slot
connections as well.
Change-Id: Id6c19dbe0c3070a131b28365584f06fb7c6014b3
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'wayland')
-rw-r--r-- | wayland/democompositor/processlauncher.cpp | 16 | ||||
-rw-r--r-- | wayland/democompositor/processlauncher.h | 3 |
2 files changed, 15 insertions, 4 deletions
diff --git a/wayland/democompositor/processlauncher.cpp b/wayland/democompositor/processlauncher.cpp index 2fb75c7..bd78de6 100644 --- a/wayland/democompositor/processlauncher.cpp +++ b/wayland/democompositor/processlauncher.cpp @@ -72,6 +72,13 @@ WaylandProcessLauncher::WaylandProcessLauncher(QObject *parent) WaylandProcessLauncher::~WaylandProcessLauncher() { + for (auto state : m_appStates) { + state.process->disconnect(state.finishedConn); + state.process->disconnect(state.errorOccurredConn); + state.process->disconnect(state.startedConn); + delete state.process; + } + m_appStates.clear(); } QVariant WaylandProcessLauncher::appStateForPid(int pid) const @@ -107,18 +114,19 @@ void WaylandProcessLauncher::launch(const AppEntry &entry) QProcess *process = new QProcess(this); process->setProcessChannelMode(QProcess::ForwardedChannels); - AppState state{process, entry}; + QMetaObject::Connection conn; + AppState state{process, entry, conn, conn, conn}; m_appStates.push_back(state); /* handle potential errors and life cycle */ - connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), + state.finishedConn = connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), [state, this](int exitCode, QProcess::ExitStatus status) { qCDebug(procs) << "AppEntry finished" << state.appEntry.executableName << exitCode << status; emit appFinished(state, exitCode, status); m_appStates.removeOne(state); state.process->deleteLater(); }); - connect(process, &QProcess::errorOccurred, + state.errorOccurredConn = connect(process, &QProcess::errorOccurred, [state, this](QProcess::ProcessError err) { qCDebug(procs) << "AppEntry error occurred" << state.appEntry.executableName << err; @@ -130,7 +138,7 @@ void WaylandProcessLauncher::launch(const AppEntry &entry) emit appNotStarted(state); state.process->deleteLater(); }); - connect(process, &QProcess::started, + state.startedConn = connect(process, &QProcess::started, [state, this]() { qCDebug(procs) << "AppEntry started" << state.appEntry.executableName; emit appStarted(state); diff --git a/wayland/democompositor/processlauncher.h b/wayland/democompositor/processlauncher.h index f21be98..3d30c07 100644 --- a/wayland/democompositor/processlauncher.h +++ b/wayland/democompositor/processlauncher.h @@ -70,6 +70,9 @@ class AppState { public: QProcess *process; AppEntry appEntry; + QMetaObject::Connection finishedConn; + QMetaObject::Connection errorOccurredConn; + QMetaObject::Connection startedConn; }; class WaylandProcessLauncher : public QObject |