File 0001-Properly-stop-list-jobs-on-close.patch of Package ark.2834
From acb455da04c473da39a5d99d4212f1d9c88abee5 Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <aacid@kde.org>
Date: Thu, 15 May 2014 00:59:32 +0200
Subject: [PATCH 1/1] Properly stop list jobs on close
Track running jobs in JobTracker. On its destruction (i.e. UI is going down) we kill and delete (which waits for finishing) those jobs.
Tested with very big tar.gz (libarchive plugin) and .zip (cliplugin) and it closes without crashing now
Acked by rakuco
BUGS: 193908
FIXED-IN: 4.13.2
REVIEW: 118108
---
kerfuffle/cliinterface.cpp | 11 +++++++++--
kerfuffle/cliinterface.h | 1 +
kerfuffle/jobs.cpp | 2 +-
part/jobtracker.cpp | 10 ++++++++++
part/jobtracker.h | 2 ++
plugins/libarchive/libarchivehandler.cpp | 10 +++++++++-
plugins/libarchive/libarchivehandler.h | 2 ++
7 files changed, 34 insertions(+), 4 deletions(-)
diff --git a/kerfuffle/cliinterface.cpp b/kerfuffle/cliinterface.cpp
index 3e835b8..eab1c6a 100644
--- a/kerfuffle/cliinterface.cpp
+++ b/kerfuffle/cliinterface.cpp
@@ -54,7 +54,8 @@ namespace Kerfuffle
CliInterface::CliInterface(QObject *parent, const QVariantList & args)
: ReadWriteArchiveInterface(parent, args),
m_process(0),
- m_listEmptyLines(false)
+ m_listEmptyLines(false),
+ m_abortingOperation(false)
{
//because this interface uses the event loop
setWaitForFinishedSignal(true);
@@ -352,6 +353,8 @@ bool CliInterface::runProcess(const QStringList& programNames, const QStringList
#else
m_process = new KPtyProcess;
m_process->setPtyChannels(KPtyProcess::StdinChannel);
+ QEventLoop loop;
+ connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)), &loop, SLOT(quit()), Qt::DirectConnection);
#endif
m_process->setOutputChannelMode(KProcess::MergedChannels);
@@ -368,7 +371,6 @@ bool CliInterface::runProcess(const QStringList& programNames, const QStringList
#ifdef Q_OS_WIN
bool ret = m_process->waitForFinished(-1);
#else
- QEventLoop loop;
bool ret = (loop.exec(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents) == 0);
#endif
@@ -427,6 +429,9 @@ void CliInterface::readStdout(bool handleAll)
//etc), so keep in mind that this function is supposed to handle
//all those special cases and be the lowest common denominator
+ if (m_abortingOperation)
+ return;
+
Q_ASSERT(m_process);
if (!m_process->bytesAvailable()) {
@@ -689,9 +694,11 @@ bool CliInterface::doKill()
{
if (m_process) {
// Give some time for the application to finish gracefully
+ m_abortingOperation = true;
if (!m_process->waitForFinished(5)) {
m_process->kill();
}
+ m_abortingOperation = false;
return true;
}
diff --git a/kerfuffle/cliinterface.h b/kerfuffle/cliinterface.h
index 7d78b4a..b4d79ed 100644
--- a/kerfuffle/cliinterface.h
+++ b/kerfuffle/cliinterface.h
@@ -338,6 +338,7 @@ private:
ParameterList m_param;
QVariantList m_removedFiles;
bool m_listEmptyLines;
+ bool m_abortingOperation;
private slots:
void readStdout(bool handleAll = false);
diff --git a/kerfuffle/jobs.cpp b/kerfuffle/jobs.cpp
index aedc62c..472a6e0 100644
--- a/kerfuffle/jobs.cpp
+++ b/kerfuffle/jobs.cpp
@@ -119,7 +119,7 @@ void Job::connectToArchiveInterfaceSignals()
connect(archiveInterface(), SIGNAL(entryRemoved(QString)), SLOT(onEntryRemoved(QString)));
connect(archiveInterface(), SIGNAL(progress(double)), SLOT(onProgress(double)));
connect(archiveInterface(), SIGNAL(info(QString)), SLOT(onInfo(QString)));
- connect(archiveInterface(), SIGNAL(finished(bool)), SLOT(onFinished(bool)));
+ connect(archiveInterface(), SIGNAL(finished(bool)), SLOT(onFinished(bool)), Qt::DirectConnection);
connect(archiveInterface(), SIGNAL(userQuery(Query*)), SLOT(onUserQuery(Query*)));
}
diff --git a/part/jobtracker.cpp b/part/jobtracker.cpp
index 15a7764..8ed0ec3 100644
--- a/part/jobtracker.cpp
+++ b/part/jobtracker.cpp
@@ -36,6 +36,14 @@ JobTracker::JobTracker(QWidget *parent)
resetUi();
}
+JobTracker::~JobTracker()
+{
+ foreach(KJob *job, m_jobs) {
+ job->kill();
+ delete job;
+ }
+}
+
void JobTracker::description(KJob *job, const QString &title, const QPair< QString, QString > &f1, const QPair< QString, QString > &f2)
{
Q_UNUSED(job)
@@ -62,6 +70,7 @@ void JobTracker::warning(KJob *job, const QString &plain, const QString &rich)
void JobTracker::registerJob(KJob *job)
{
+ m_jobs << job;
KJobTrackerInterface::registerJob(job);
m_ui->show();
m_ui->informationLabel->hide();
@@ -78,6 +87,7 @@ void JobTracker::percent(KJob *job, unsigned long percent)
void JobTracker::unregisterJob(KJob *job)
{
+ m_jobs.remove(job);
KJobTrackerInterface::unregisterJob(job);
resetUi();
}
diff --git a/part/jobtracker.h b/part/jobtracker.h
index 356a558..08aa77a 100644
--- a/part/jobtracker.h
+++ b/part/jobtracker.h
@@ -42,6 +42,7 @@ class JobTracker: public KAbstractWidgetJobTracker
public:
JobTracker(QWidget *parent = 0);
+ ~JobTracker();
virtual QWidget *widget(KJob *);
@@ -61,6 +62,7 @@ private slots:
private:
JobTrackerWidget *m_ui;
+ QSet<KJob*> m_jobs;
};
#endif // JOBTRACKER_H
diff --git a/plugins/libarchive/libarchivehandler.cpp b/plugins/libarchive/libarchivehandler.cpp
index cd473ee..0fba528 100644
--- a/plugins/libarchive/libarchivehandler.cpp
+++ b/plugins/libarchive/libarchivehandler.cpp
@@ -72,6 +72,7 @@ LibArchiveInterface::LibArchiveInterface(QObject *parent, const QVariantList & a
, m_extractedFilesSize(0)
, m_workDir(QDir::current())
, m_archiveReadDisk(archive_read_disk_new())
+ , m_abortOperation(false)
{
archive_read_disk_set_standard_lookup(m_archiveReadDisk.data());
}
@@ -110,7 +111,7 @@ bool LibArchiveInterface::list()
struct archive_entry *aentry;
int result;
- while ((result = archive_read_next_header(arch_reader.data(), &aentry)) == ARCHIVE_OK) {
+ while (!m_abortOperation && (result = archive_read_next_header(arch_reader.data(), &aentry)) == ARCHIVE_OK) {
if (!m_emitNoEntries) {
emitEntryFromArchiveEntry(aentry);
}
@@ -120,6 +121,7 @@ bool LibArchiveInterface::list()
m_cachedArchiveEntryCount++;
archive_read_data_skip(arch_reader.data());
}
+ m_abortOperation = false;
if (result != ARCHIVE_EOF) {
emit error(i18nc("@info", "The archive reading failed with the following error: <message>%1</message>",
@@ -130,6 +132,12 @@ bool LibArchiveInterface::list()
return archive_read_close(arch_reader.data()) == ARCHIVE_OK;
}
+bool LibArchiveInterface::doKill()
+{
+ m_abortOperation = true;
+ return true;
+}
+
bool LibArchiveInterface::copyFiles(const QVariantList& files, const QString& destinationDirectory, ExtractionOptions options)
{
kDebug() << "Changing current directory to " << destinationDirectory;
diff --git a/plugins/libarchive/libarchivehandler.h b/plugins/libarchive/libarchivehandler.h
index 9ec7541..088c0fe 100644
--- a/plugins/libarchive/libarchivehandler.h
+++ b/plugins/libarchive/libarchivehandler.h
@@ -45,6 +45,7 @@ public:
~LibArchiveInterface();
bool list();
+ bool doKill();
bool copyFiles(const QVariantList& files, const QString& destinationDirectory, ExtractionOptions options);
bool addFiles(const QStringList& files, const CompressionOptions& options);
bool deleteFiles(const QVariantList& files);
@@ -68,6 +69,7 @@ private:
QDir m_workDir;
QStringList m_writtenFiles;
ArchiveRead m_archiveReadDisk;
+ bool m_abortOperation;
};
#endif // LIBARCHIVEHANDLER_H
--
1.9.3