From 21296bba7154840d0127ef68712f80a3424d9f98 Mon Sep 17 00:00:00 2001 From: MinyazevR Date: Wed, 30 Oct 2024 15:27:56 +0300 Subject: [PATCH] Block TrikScriptRunnerWorker thread when reading values from sensors --- .../src/trikEmulation/triklinesensoradapter.cpp | 13 ++++++++++++- .../src/trikEmulation/triksensoremu.cpp | 14 +++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triklinesensoradapter.cpp b/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triklinesensoradapter.cpp index f2fb4db213..8ef55d0308 100644 --- a/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triklinesensoradapter.cpp +++ b/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triklinesensoradapter.cpp @@ -37,7 +37,18 @@ void TrikLineSensorAdapter::detect() QVector TrikLineSensorAdapter::read() { - QMetaObject::invokeMethod(mLineSensor, "read"); + /* Sensor values are calculated by timer in the UI Thread + * (subscription in plugins/robots/interpreters/trikKitInterpreterCommon/src/TrikBrick) + * and are also forced through TrikScriptRunner when calculating sensor values (except for Gyroscope::read). + * This heavily loads the UI thread, and in incorrect code like + * while (true) { brick.lineSensor("video1").read(); } + * the UI thread gets blocked by sensor reading tasks, making the user interface non-functional. + * As a hot-fix, it is proposed to calculate values using Qt::BlockingQueuedConnection, + * which will force waiting for the sensor value calculation instead of queuing new tasks + * in the UI thread every few milliseconds (this is critical for reading from sensors + * whose handlers take a relatively long time, as the queue contains many reading tasks + * while returning old (already calculated) sensor values, which forces new tasks to be queued). */ + QMetaObject::invokeMethod(mLineSensor, "read", Qt::BlockingQueuedConnection); return mLineSensor->lastData(); // hopefully the same format } diff --git a/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triksensoremu.cpp b/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triksensoremu.cpp index f06ca6ff0e..20624f3ccd 100644 --- a/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triksensoremu.cpp +++ b/plugins/robots/interpreters/trikKitInterpreterCommon/src/trikEmulation/triksensoremu.cpp @@ -24,6 +24,18 @@ TrikSensorEmu::TrikSensorEmu(kitBase::robotModel::robotParts::ScalarSensor *sens int TrikSensorEmu::read() { //mSensor->read(); test crash fixes - QMetaObject::invokeMethod(mSensor, "read"); + + /* Sensor values are calculated by timer in the UI Thread + * (subscription in plugins/robots/interpreters/trikKitInterpreterCommon/src/TrikBrick) + * and are also forced through TrikScriptRunner when calculating sensor values (except for Gyroscope::read). + * This heavily loads the UI thread, and in incorrect code like + * while (true) { brick.sensor("A1").read() } + * the UI thread gets blocked by sensor reading tasks, making the user interface non-functional. + * As a hot-fix, it is proposed to calculate values using Qt::BlockingQueuedConnection, + * which will force waiting for the sensor value calculation instead of queuing new tasks + * in the UI thread every few milliseconds (this is critical for reading from sensors + * whose handlers take a relatively long time, as the queue contains many reading tasks + * while returning old (already calculated) sensor values, which forces new tasks to be queued). */ + QMetaObject::invokeMethod(mSensor, "read", Qt::BlockingQueuedConnection); return mSensor->lastData(); // not best, race conditions? }