mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-17 02:45:33 +08:00
Issue #11 CEventLoop uses QPointer trick to guard against use-after-free
See https://blogs.kde.org/2009/03/26/how-crash-almost-every-qtkde-application-and-how-fix-it-0
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QEventLoop>
|
||||
#include <QPointer>
|
||||
#include <QTimer>
|
||||
|
||||
namespace BlackMisc
|
||||
@@ -25,6 +26,16 @@ namespace BlackMisc
|
||||
class CEventLoop
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
CEventLoop() : m_guard(&m_eventLoop) {}
|
||||
|
||||
//! Constructor. Guard object must exist, and will be checked again when the loop quits.
|
||||
CEventLoop(QObject *guard) : m_guard(guard)
|
||||
{
|
||||
Q_ASSERT(guard);
|
||||
QObject::connect(guard, &QObject::destroyed, &m_eventLoop, [this] { m_eventLoop.exit(TimedOut); });
|
||||
}
|
||||
|
||||
//! Event loop will stop if the given signal is received.
|
||||
template <typename T, typename F>
|
||||
void stopWhen(const T *sender, F signal)
|
||||
@@ -43,14 +54,20 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
//! Begin processing events until the timeout or stop condition occurs.
|
||||
//! \return True if the signal was received, false if it timed out.
|
||||
//! \return True if the signal was received, false if it timed out or the guard object died.
|
||||
bool exec(int timeoutMs)
|
||||
{
|
||||
if (timeoutMs >= 0)
|
||||
{
|
||||
QTimer::singleShot(timeoutMs, &m_eventLoop, [this] { m_eventLoop.exit(TimedOut); });
|
||||
}
|
||||
return m_eventLoop.exec() == GotSignal;
|
||||
return m_eventLoop.exec() == GotSignal && isGuardAlive();
|
||||
}
|
||||
|
||||
//! True if the guard object still exists.
|
||||
bool isGuardAlive() const
|
||||
{
|
||||
return m_guard;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -60,6 +77,7 @@ namespace BlackMisc
|
||||
TimedOut,
|
||||
};
|
||||
QEventLoop m_eventLoop;
|
||||
QPointer<QObject> m_guard;
|
||||
};
|
||||
} // ns
|
||||
|
||||
|
||||
Reference in New Issue
Block a user