Commit e1c19ce4 authored by Oleg Solovyov's avatar Oleg Solovyov Committed by Nate Graham

Plasmashell freezes when trying to get free space info from mounted remote...

Plasmashell freezes when trying to get free space info from mounted remote filesystem after losing connection to it

Summary:
BUG: 397537

Earlier plasmashell assumed that you'll get free space info immediately (which is not true in case of losing connection to server containing a mounted filesystem - statfs will wait for response forever and freeze everything since it's happening in main thread)

I moved obtaining that info into different thread so that case won't freeze anything anymore.
It creates exactly one thread per one path. If a path is already being processed, new thread won't be created.
Also I implemented a timer used to notify about broken connection after 15 seconds.

Reviewers: broulik, ngraham, davidedmundson

Reviewed By: broulik

Subscribers: ngraham, anthonyfieroni, davidedmundson, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D14895
parent 2949e7c4
......@@ -18,6 +18,7 @@ target_link_libraries(plasma_engine_soliddevice
KF5::Plasma
KF5::Solid
KF5::CoreAddons
KF5::Notifications
)
kcoreaddons_desktop_to_json(plasma_engine_soliddevice plasma-dataengine-soliddevice.desktop)
......
......@@ -24,9 +24,11 @@
#include <Solid/GenericInterface>
#include <klocalizedstring.h>
#include <QApplication>
#include <QDebug>
#include <KDiskFreeSpaceInfo>
#include <KFormat>
#include <KIO/FileSystemFreeSpaceJob>
#include <KNotification>
#include <Plasma/DataContainer>
......@@ -547,12 +549,39 @@ bool SolidDeviceEngine::updateStorageSpace(const QString &udi)
return false;
}
KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(storageaccess->filePath());
if (info.isValid()) {
setData(udi, I18N_NOOP("Free Space"), QVariant(info.available()));
setData(udi, I18N_NOOP("Free Space Text"), KFormat().formatByteSize(info.available()));
setData(udi, I18N_NOOP("Size"), QVariant(info.size()));
return true;
QString path = storageaccess->filePath();
if (!m_paths.contains(path)) {
QTimer *timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, &QTimer::timeout, [path]() {
KNotification::event(KNotification::Error, i18n("Filesystem is not responding", path),
i18n("Filesystem mounted at '%1' is not responding", path));
});
m_paths.insert(path);
// create job
KIO::FileSystemFreeSpaceJob *job = KIO::fileSystemFreeSpace(QUrl::fromLocalFile(path));
// delete later timer
connect(job, &KIO::FileSystemFreeSpaceJob::result, timer, &QTimer::deleteLater);
// collect and process info
connect(job, &KIO::FileSystemFreeSpaceJob::result, this,
[this, timer, path, udi](KIO::Job *job, KIO::filesize_t size, KIO::filesize_t available) {
timer->stop();
if (!job->error()) {
setData(udi, I18N_NOOP("Free Space"), QVariant(available));
setData(udi, I18N_NOOP("Free Space Text"), KFormat().formatByteSize(available));
setData(udi, I18N_NOOP("Size"), QVariant(size));
}
m_paths.remove(path);
});
// start timer: after 15 seconds we will get an error
timer->start(15000);
}
return false;
......
......@@ -35,6 +35,7 @@
#include "devicesignalmapmanager.h"
#include "devicesignalmapper.h"
#include "hddtemp.h"
#include <KIO/FileSystemFreeSpaceJob>
enum State {
Idle = 0,
......@@ -80,6 +81,8 @@ private:
QMap<QString, Solid::Device> m_devicemap;
//udi, corresponding encrypted container udi;
QMap<QString, QString> m_encryptedContainerMap;
//path, corresponding timer
QSet<QString> m_paths;
DeviceSignalMapManager *m_signalmanager;
HddTemp *m_temperature;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment