Commit a0fd2014 authored by Milian Wolff's avatar Milian Wolff

Don't crash when background listing outlasts file manager list job

When the QDir listing in the background thread takes a long time,
e.g. by artificially introducing a sleep statement therein, then
it can happen that the FileManagerListJob gets destroyed before
the background task finishes. If that happens, then we used to
access the dangling this pointer to access m_aborted or to invoke
the handleResults method, both of which are undefined behavior.
The latter usually crashes.

Prevent this from happening by introducing a mutex that gets locked
while we are running a background task and during destruction of
the list job. This synchronizes the two tasks and prevents the
crash from happening.
parent 3aed7ac4
......@@ -64,6 +64,13 @@ FileManagerListJob::FileManagerListJob(ProjectFolderItem* item)
#endif
}
FileManagerListJob::~FileManagerListJob()
{
// lock and abort to ensure our background list job is stopped
std::lock_guard<std::mutex> lock(m_listing);
m_aborted = true;
}
void FileManagerListJob::addSubDir( ProjectFolderItem* item )
{
Q_ASSERT(!m_listQueue.contains(item));
......@@ -103,7 +110,10 @@ void FileManagerListJob::startNextJob()
m_item = m_listQueue.dequeue();
if (m_item->path().isLocalFile()) {
// optimized version for local projects using QDir directly
// start locking to ensure we don't get destroyed while waiting for the list to finish
m_listing.lock();
QtConcurrent::run([this] (const Path& path) {
std::lock_guard<std::mutex> lock(m_listing, std::adopt_lock);
if (m_aborted) {
return;
}
......
......@@ -23,6 +23,8 @@
#include <KIO/Job>
#include <QQueue>
#include <mutex>
// uncomment to time import jobs
// #define TIME_IMPORT_JOB
......@@ -41,6 +43,7 @@ class FileManagerListJob : public KIO::Job
public:
explicit FileManagerListJob(ProjectFolderItem* item);
virtual ~FileManagerListJob();
void addSubDir(ProjectFolderItem* item);
void handleRemovedItem(ProjectBaseItem* item);
......@@ -67,6 +70,7 @@ private:
KIO::UDSEntryList entryList;
// kill does not delete the job instantaneously
QAtomicInt m_aborted;
std::mutex m_listing;
#ifdef TIME_IMPORT_JOB
QElapsedTimer m_timer;
......
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