Fix illegal cross-thread UI calls
MODIFY
src/statusmanager.h
src/statusmanager.h
#pragma once
+#include <QAbstractEventDispatcher>
+#include <QApplication>
#include <QObject>
#include <QString>
#include <QStringList>
#include <memory>
namespace Ripes {
+
+/**
+ * @brief postToGUIThread
+ * Schedules the execution of @param fun in the GUI thread.
+ * @param connection type.
+ */
+template <typename F>
+static void postToGUIThread(F&& fun, Qt::ConnectionType type = Qt::QueuedConnection) {
+ auto* obj = QAbstractEventDispatcher::instance(qApp->thread());
+ Q_ASSERT(obj);
+ QMetaObject::invokeMethod(obj, std::forward<F>(fun), type);
+}
+
class StatusEmitter : public QObject {
Q_OBJECT
public:

MODIFY
src/syscall/ripes_syscall.cpp
src/syscall/ripes_syscall.cpp
@@ -16,10 +16,15 @@ bool SyscallManager::execute(SyscallID id) {
return false;
} else {
const auto& syscall = m_syscalls.at(id);
- SyscallStatusManager::setStatusTimed("Handling system call: " + syscall->name() + " (" + QString::number(id) +
- ")");
+ const QString& syscallName = syscall->name();
+ postToGUIThread([=] {
+ // We don't have a good way of making non-permanent status timers pseudo-permanent until explicitly
+ // cleared... The best way to do so is to just have a very large timeout.
+ SyscallStatusManager::setStatusTimed(
+ "Handling system call: " + syscallName + " (" + QString::number(id) + ")", 99999999);
+ });
syscall->execute();
- SyscallStatusManager::clearStatus();
+ postToGUIThread([=] { SyscallStatusManager::clearStatus(); });
return true;
}
}

MODIFY
src/syscall/ripes_syscall.h
src/syscall/ripes_syscall.h
#pragma once
-#include <QAbstractEventDispatcher>
#include <QApplication>
#include <QLabel>
#include <QMessageBox>
@@ -80,18 +79,6 @@ public:
const std::map<SyscallID, std::unique_ptr<Syscall>>& getSyscalls() const { return m_syscalls; }
protected:
- /**
- * @brief postToGUIThread
- * Schedules the execution of @param fun in the GUI thread.
- * @param connection type.
- */
- template <typename F>
- static void postToGUIThread(F&& fun, Qt::ConnectionType type = Qt::QueuedConnection) {
- auto* obj = QAbstractEventDispatcher::instance(qApp->thread());
- Q_ASSERT(obj);
- QMetaObject::invokeMethod(obj, std::forward<F>(fun), type);
- }
-
SyscallManager() {}
std::map<SyscallID, std::unique_ptr<Syscall>> m_syscalls;
};

MODIFY
src/syscall/systemio.h
src/syscall/systemio.h
@@ -324,7 +324,8 @@ public:
auto& InputStream = FileIOData::getStreamInUse(fd);
if (fd == STDIN) {
- SystemIOStatusManager::setStatusTimed("Waiting for user input...");
+ // systemIO might be called from non-gui thread, so be threadsafe in interacting with the ui.
+ postToGUIThread([=] { SystemIOStatusManager::setStatusTimed("Waiting for user input...", 99999999); });
while (myBuffer.size() == 0) {
// Lock the stdio objects and try to read from stdio. If no data is present, wait until so.
FileIOData::s_stdioMutex.lock();
@@ -358,7 +359,7 @@ public:
}
}
- SystemIOStatusManager::clearStatus();
+ postToGUIThread([=] { SystemIOStatusManager::clearStatus(); });
return myBuffer.size();
} // end readFromFile

Fix illegal cross-thread UI calls