Commit 1bae2b0b authored by Ingo Klöcker's avatar Ingo Klöcker
Browse files

Fix canceling of import command

If a job is canceled, then the result signal is still emitted. This
caused an assert (or a crash) because in doCancel() the list of jobs
was cleared, but in the slot connected to the result signal the job
was still looked up in the (empty) list of jobs.

To fix this we disconnect all connections and call the importResult() slot
manually for all canceled jobs.

GnuPG-bug-id: 5805
parent 9d66f48d
......@@ -470,15 +470,21 @@ void ImportCertificatesCommand::Private::setWaitForMoreJobs(bool wait)
}
}
void ImportCertificatesCommand::Private::importResult(const ImportResult &result)
void ImportCertificatesCommand::Private::importResult(const ImportResult &result, QGpgME::Job *finishedJob)
{
const auto finishedJob = q->sender();
if (!finishedJob) {
finishedJob = qobject_cast<QGpgME::Job *>(q->sender());
}
Q_ASSERT(finishedJob);
auto it = std::find_if(std::cbegin(jobs), std::cend(jobs),
[finishedJob](const auto &job) { return job.job == finishedJob; });
Q_ASSERT(it != std::cend(jobs));
if (it == std::cend(jobs)) {
qCWarning(KLEOPATRA_LOG) << __func__ << "Error: Finished job not found";
return;
}
const auto job = *it;
jobs.erase(std::remove(std::begin(jobs), std::end(jobs), job), std::end(jobs));
......@@ -722,10 +728,12 @@ void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, c
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult)));
connect(job.get(), &Job::progress,
q, &Command::progress);
std::vector<QMetaObject::Connection> connections = {
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult))),
connect(job.get(), &Job::progress,
q, &Command::progress)
};
#ifdef QGPGME_SUPPORTS_IMPORT_WITH_FILTER
job->setImportFilter(options.importFilter);
......@@ -737,7 +745,7 @@ void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, c
if (err.code()) {
importResult({id, protocol, ImportType::Local, ImportResult{err}});
} else {
jobs.push_back({id, protocol, ImportType::Local, job.release()});
jobs.push_back({id, protocol, ImportType::Local, job.release(), connections});
}
}
......@@ -771,15 +779,18 @@ void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, c
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult)));
connect(job.get(), &Job::progress,
q, &Command::progress);
std::vector<QMetaObject::Connection> connections = {
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult))),
connect(job.get(), &Job::progress,
q, &Command::progress)
};
const GpgME::Error err = job->start(keys);
if (err.code()) {
importResult({id, protocol, ImportType::External, ImportResult{err}});
} else {
jobs.push_back({id, protocol, ImportType::External, job.release()});
jobs.push_back({id, protocol, ImportType::External, job.release(), connections});
}
}
......@@ -812,15 +823,18 @@ void ImportCertificatesCommand::Private::startImport(GpgME::Protocol protocol, c
#ifdef QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID
keyCacheAutoRefreshSuspension = KeyCache::mutableInstance()->suspendAutoRefresh();
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult)));
connect(job.get(), &Job::progress,
q, &Command::progress);
std::vector<QMetaObject::Connection> connections = {
connect(job.get(), SIGNAL(result(GpgME::ImportResult)),
q, SLOT(importResult(GpgME::ImportResult))),
connect(job.get(), &Job::progress,
q, &Command::progress)
};
const GpgME::Error err = job->start(keyIds);
if (err.code()) {
importResult({id, protocol, ImportType::External, ImportResult{err}});
} else {
jobs.push_back({id, protocol, ImportType::External, job.release()});
jobs.push_back({id, protocol, ImportType::External, job.release(), connections});
}
#endif
}
......@@ -833,8 +847,12 @@ void ImportCertificatesCommand::Private::importGroupsFromFile(const QString &fil
void ImportCertificatesCommand::doCancel()
{
std::for_each(std::cbegin(d->jobs), std::cend(d->jobs),
[](const auto &job) { job.job->slotCancel(); });
d->jobs.clear();
[this](const auto &job) {
std::for_each(std::cbegin(job.connections), std::cend(job.connections),
[](const auto &connection) { QObject::disconnect(connection); });
job.job->slotCancel();
d->importResult(ImportResult{Error::fromCode(GPG_ERR_CANCELED)}, job.job);
});
}
#undef d
......
......@@ -31,7 +31,7 @@ class Error;
namespace QGpgME
{
class AbstractImportJob;
class Job;
}
namespace Kleo
......@@ -52,7 +52,8 @@ struct ImportJobData
QString id;
GpgME::Protocol protocol;
ImportType type;
QGpgME::AbstractImportJob *job;
QGpgME::Job *job;
std::vector<QMetaObject::Connection> connections;
};
bool operator==(const ImportJobData &lhs, const ImportJobData &rhs);
......@@ -101,7 +102,7 @@ public:
void startImport(GpgME::Protocol proto, const QByteArray &data, const QString &id = QString(), const ImportOptions &options = {});
void startImport(GpgME::Protocol proto, const std::vector<GpgME::Key> &keys, const QString &id = QString());
void startImport(GpgME::Protocol proto, const QStringList &keyIds, const QString &id = {});
void importResult(const GpgME::ImportResult &);
void importResult(const GpgME::ImportResult &, QGpgME::Job *job = nullptr);
void importResult(const ImportResultData &result);
void importGroupsFromFile(const QString &filename);
......
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