From 3a9e30eb6229a6212150dbc1a3627246d51c8be2 Mon Sep 17 00:00:00 2001 From: Thomas McGuire Date: Wed, 27 Feb 2013 09:35:05 +0100 Subject: Blackberry: Prevent spurious calls to dataAvailable() when stopped Explicitly disable the socket notifier and drain the device file to avoid dataAvailable() being called spuriously. This fixes high CPU usage that occurred in some circumstances after stopping the sensor. Many thanks to Dmytro Mishchenko for reporting and helping to track down the problem. Change-Id: Idcaff1432b96b392d033e5b21c2b379259792212 Reviewed-by: Adam Parco Reviewed-by: Lorn Potter --- src/plugins/sensors/blackberry/bbsensorbackend.cpp | 35 ++++++++++++++-------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/plugins/sensors/blackberry/bbsensorbackend.cpp b/src/plugins/sensors/blackberry/bbsensorbackend.cpp index fec40c5..a244a97 100644 --- a/src/plugins/sensors/blackberry/bbsensorbackend.cpp +++ b/src/plugins/sensors/blackberry/bbsensorbackend.cpp @@ -130,6 +130,19 @@ void BbSensorBackendBase::initSensorInfo() qDebug() << "Failed to open sensor" << m_deviceFile.fileName() << ":" << m_deviceFile.errorString(); } else { + + // Explicitly switch to non-blocking mode, otherwise read() will wait until new sensor + // data is available, and we have no way to check if there is more data or not (bytesAvailable() + // does not work for unbuffered mode) + const int oldFlags = fcntl(m_deviceFile.handle(), F_GETFL); + if (fcntl(m_deviceFile.handle(), F_SETFL, oldFlags | O_NONBLOCK) == -1) { + perror(QString::fromLatin1("Starting sensor %1 failed, fcntl() returned -1") + .arg(m_deviceFile.fileName()).toLocal8Bit()); + sensorError(errno); + stop(); + return; + } + sensor_devctl_info_u deviceInfo; const int result = devctl(m_deviceFile.handle(), DCMD_SENSOR_INFO, &deviceInfo, sizeof(deviceInfo), NULL); @@ -156,6 +169,7 @@ void BbSensorBackendBase::initSensorInfo() setPaused(true); m_socketNotifier.reset(new QSocketNotifier(m_deviceFile.handle(), QSocketNotifier::Read)); + m_socketNotifier->setEnabled(false); connect(m_socketNotifier.data(), SIGNAL(activated(int)), this, SLOT(dataAvailable())); } } @@ -267,18 +281,6 @@ void BbSensorBackendBase::start() .arg(m_deviceFile.fileName()).toLocal8Bit()); } - // Explicitly switch to non-blocking mode, otherwise read() will wait until new sensor - // data is available, and we have no way to check if there is more data or not (bytesAvailable() - // does not work for unbuffered mode) - const int oldFlags = fcntl(m_deviceFile.handle(), F_GETFL); - if (fcntl(m_deviceFile.handle(), F_SETFL, oldFlags | O_NONBLOCK) == -1) { - perror(QString::fromLatin1("Starting sensor %1 failed, fcntl() returned -1") - .arg(m_deviceFile.fileName()).toLocal8Bit()); - sensorError(errno); - stop(); - return; - } - applyBuffering(); applyAlwaysOnProperty(); } @@ -313,8 +315,12 @@ bool BbSensorBackendBase::isFeatureSupported(QSensor::Feature feature) const void BbSensorBackendBase::dataAvailable() { - if (!m_started) + if (!m_started) { + // Spurious dataAvailable() call, drain the device file of data. We also disable + // the socket notifier for this, so this is just added safety here. + m_deviceFile.readAll(); return; + } Q_FOREVER { sensor_event_t event; @@ -397,6 +403,9 @@ bool BbSensorBackendBase::setPaused(bool paused) sensor_devctl_enable_u enableState; enableState.tx.enable = paused ? 0 : 1; + if (m_socketNotifier) + m_socketNotifier->setEnabled(!paused); + const int result = devctl(m_deviceFile.handle(), DCMD_SENSOR_ENABLE, &enableState, sizeof(enableState), NULL); if (result != EOK) { perror(QString::fromLatin1("Setting sensor enabled (%1) for %2 failed") -- cgit v1.2.1