Commit acb455da authored by Albert Astals Cid's avatar Albert Astals Cid

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
parent 40ea8b07
......@@ -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;
}
......
......@@ -338,6 +338,7 @@ private:
ParameterList m_param;
QVariantList m_removedFiles;
bool m_listEmptyLines;
bool m_abortingOperation;
private slots:
void readStdout(bool handleAll = false);
......
......@@ -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*)));
}
......
......@@ -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();
}
......
......@@ -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
......@@ -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;
......
......@@ -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
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