diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/GpgContext.cpp | 73 | ||||
-rw-r--r-- | src/core/GpgContext.h | 5 | ||||
-rw-r--r-- | src/core/GpgInfo.h | 27 | ||||
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.cpp | 126 | ||||
-rw-r--r-- | src/core/function/gpg/GpgCommandExecutor.h | 7 | ||||
-rw-r--r-- | src/core/thread/CtxCheckTask.cpp | 3 | ||||
-rw-r--r-- | src/core/thread/FileReadTask.cpp | 2 | ||||
-rw-r--r-- | src/core/thread/Task.cpp | 54 | ||||
-rw-r--r-- | src/core/thread/Task.h | 27 | ||||
-rw-r--r-- | src/core/thread/TaskRunner.cpp | 45 | ||||
-rw-r--r-- | src/core/thread/TaskRunner.h | 1 | ||||
-rw-r--r-- | src/ui/UserInterfaceUtils.cpp | 22 | ||||
-rw-r--r-- | src/ui/dialog/help/GnupgTab.cpp | 7 | ||||
-rw-r--r-- | src/ui/thread/KeyServerImportTask.cpp | 3 | ||||
-rw-r--r-- | src/ui/thread/KeyServerSearchTask.cpp | 3 | ||||
-rw-r--r-- | src/ui/thread/ListedKeyServerTestTask.cpp | 3 | ||||
-rw-r--r-- | src/ui/thread/VersionCheckTask.cpp | 3 |
17 files changed, 315 insertions, 96 deletions
diff --git a/src/core/GpgContext.cpp b/src/core/GpgContext.cpp index 9f69522a..613767a7 100644 --- a/src/core/GpgContext.cpp +++ b/src/core/GpgContext.cpp @@ -32,6 +32,8 @@ #include <gpgme.h> #include <unistd.h> +#include <mutex> +#include <shared_mutex> #include <string> #include "core/GpgConstants.h" @@ -159,10 +161,12 @@ GpgContext::GpgContext(const GpgContextInitArgs &args) : args_(args) { // async, init context Thread::TaskRunnerGetter::GetInstance() .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_GPG) - ->PostTask(new Thread::Task([=](Thread::Task::DataObjectPtr) -> int { - post_init_ctx(); - return 0; - })); + ->PostTask(new Thread::Task( + [=](Thread::Task::DataObjectPtr) -> int { + post_init_ctx(); + return 0; + }, + "post_init_ctx")); good_ = true; } @@ -213,7 +217,7 @@ void GpgContext::post_init_ctx() { } // preload info - auto info = GetInfo(); + auto &info = GetInfo(); // listen passphrase input event SetPassphraseCb(custom_passphrase_cb); @@ -321,6 +325,15 @@ std::string GpgContext::need_user_input_passphrase() { const GpgInfo &GpgContext::GetInfo(bool refresh) { if (!extend_info_loaded_ || refresh) { + // try lock + std::unique_lock lock(preload_lock_); + + // check twice + if (extend_info_loaded_ && !refresh) return info_; + + SPDLOG_DEBUG("start to load extra info"); + + // get all components GpgCommandExecutor::GetInstance().Execute( info_.GpgConfPath, {"--list-components"}, [=](int exit_code, const std::string &p_out, const std::string &p_err) { @@ -382,13 +395,19 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { info_.KeyboxdPath = info_split_list[2]; } - // add component info to list - components_info[component_name] = { - component_desc, version, component_path, - binary_checksum.has_value() ? binary_checksum.value() : "/"}; + { + // try lock + std::unique_lock lock(info_.Lock); + // add component info to list + components_info[component_name] = { + component_desc, version, component_path, + binary_checksum.has_value() ? binary_checksum.value() : "/"}; + } } }); + SPDLOG_DEBUG("start to get dirs info"); + GpgCommandExecutor::GetInstance().Execute( info_.GpgConfPath, {"--list-dirs"}, [=](int exit_code, const std::string &p_out, const std::string &p_err) { @@ -423,10 +442,16 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { } auto configuration_name = info_split_list[0]; - configurations_info[configuration_name] = {info_split_list[1]}; + { + // try lock + std::unique_lock lock(info_.Lock); + configurations_info[configuration_name] = {info_split_list[1]}; + } } }); + SPDLOG_DEBUG("start to get components info"); + for (const auto &component : info_.ComponentsInfo) { SPDLOG_DEBUG("gpgconf check options ready", "component", component.first); @@ -464,13 +489,19 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { if (info_split_list.size() != 6) continue; auto configuration_name = info_split_list[0]; - options_info[configuration_name] = { - info_split_list[1], info_split_list[2], info_split_list[3], - info_split_list[4], info_split_list[5]}; + { + // try lock + std::unique_lock lock(info_.Lock); + options_info[configuration_name] = { + info_split_list[1], info_split_list[2], info_split_list[3], + info_split_list[4], info_split_list[5]}; + } } }); } + SPDLOG_DEBUG("start to get component options info"); + for (const auto &component : info_.ComponentsInfo) { SPDLOG_DEBUG("gpgconf list options ready", "component", component.first); @@ -508,16 +539,22 @@ const GpgInfo &GpgContext::GetInfo(bool refresh) { if (info_split_list.size() != 10) continue; auto configuration_name = info_split_list[0]; - available_options_info[configuration_name] = { - info_split_list[1], info_split_list[2], info_split_list[3], - info_split_list[4], info_split_list[5], info_split_list[6], - info_split_list[7], info_split_list[8], info_split_list[9]}; + { + // try lock + std::unique_lock lock(info_.Lock); + available_options_info[configuration_name] = { + info_split_list[1], info_split_list[2], info_split_list[3], + info_split_list[4], info_split_list[5], info_split_list[6], + info_split_list[7], info_split_list[8], info_split_list[9]}; + } } }); } - extend_info_loaded_ = true; } + + // ensure nothing is changing now + std::shared_lock lock(preload_lock_); return info_; } diff --git a/src/core/GpgContext.h b/src/core/GpgContext.h index 79d76fe2..384271a6 100644 --- a/src/core/GpgContext.h +++ b/src/core/GpgContext.h @@ -107,9 +107,10 @@ class GPGFRONTEND_CORE_EXPORT GpgContext operator gpgme_ctx_t() const { return _ctx_ref.get(); } private: - GpgInfo info_; ///< - GpgContextInitArgs args_; ///< + GpgInfo info_{}; ///< + GpgContextInitArgs args_{}; ///< bool extend_info_loaded_ = false; + std::shared_mutex preload_lock_{}; /** * @brief diff --git a/src/core/GpgInfo.h b/src/core/GpgInfo.h index 115b7911..f4415af1 100644 --- a/src/core/GpgInfo.h +++ b/src/core/GpgInfo.h @@ -29,6 +29,7 @@ #ifndef GPGFRONTEND_ZH_CN_TS_GPGINFO_H #define GPGFRONTEND_ZH_CN_TS_GPGINFO_H +#include <mutex> #include <string> namespace GpgFrontend { @@ -38,22 +39,26 @@ namespace GpgFrontend { */ class GpgInfo { public: - std::string AppPath; ///< executable binary path of gnupg - std::string DatabasePath; ///< - std::string GnupgVersion; ///< - std::string GpgConfPath; ///< - std::string AssuanPath; ///< - std::string CMSPath; ///< - std::string GpgAgentPath; ///< - std::string DirmngrPath; ///< - std::string KeyboxdPath; ///< - std::string GpgMEVersion; ///< - std::string GnuPGHomePath; ///< + std::string GnupgVersion; ///< version of gnupg + std::string GpgMEVersion; ///< + + std::string AppPath; ///< executable binary path of gnupg + std::string DatabasePath; ///< key database path + std::string GpgConfPath; ///< executable binary path of gpgconf + std::string AssuanPath; ///< executable binary path of assuan + std::string CMSPath; ///< executable binary path of cms + std::string GpgAgentPath; ///< executable binary path of gpg-agent + std::string DirmngrPath; ///< executable binary path of dirmgr + std::string KeyboxdPath; ///< executable binary path of keyboxd + + std::string GnuPGHomePath; ///< value of ---homedir std::map<std::string, std::vector<std::string>> ComponentsInfo; ///< std::map<std::string, std::vector<std::string>> ConfigurationsInfo; ///< std::map<std::string, std::vector<std::string>> OptionsInfo; ///< std::map<std::string, std::vector<std::string>> AvailableOptionsInfo; ///< + + std::shared_mutex Lock; }; } // namespace GpgFrontend diff --git a/src/core/function/gpg/GpgCommandExecutor.cpp b/src/core/function/gpg/GpgCommandExecutor.cpp index 670dae0c..30984697 100644 --- a/src/core/function/gpg/GpgCommandExecutor.cpp +++ b/src/core/function/gpg/GpgCommandExecutor.cpp @@ -29,6 +29,7 @@ #include "GpgFunctionObject.h" #include "core/thread/TaskRunnerGetter.h" +#include "spdlog/fmt/bundled/format.h" GpgFrontend::GpgCommandExecutor::GpgCommandExecutor(int channel) : SingletonFunctionObject<GpgCommandExecutor>(channel) {} @@ -79,9 +80,8 @@ void GpgFrontend::GpgCommandExecutor::Execute( [interact_func, cmd_process]() { interact_func(cmd_process); }); QObject::connect(cmd_process, &QProcess::errorOccurred, [=](QProcess::ProcessError error) { - SPDLOG_ERROR( - "error in executing command: {} error: {}", - cmd, error); + SPDLOG_ERROR("error in executing command: {} error: {}", + cmd, error); }); QObject::connect( cmd_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), @@ -94,7 +94,8 @@ void GpgFrontend::GpgCommandExecutor::Execute( else SPDLOG_ERROR( "proceess finished, error in executing command: {}, exit " - "status: {}", cmd, status); + "status: {}", + cmd, status); }); cmd_process->setProgram(QString::fromStdString(cmd)); @@ -104,7 +105,8 @@ void GpgFrontend::GpgCommandExecutor::Execute( q_arguments.append(QString::fromStdString(argument)); cmd_process->setArguments(q_arguments); - SPDLOG_DEBUG("process execute ready"); + SPDLOG_DEBUG("process execute ready, cmd: {} {}", cmd, + q_arguments.join(" ").toStdString()); cmd_process->start(); cmd_process->waitForFinished(); @@ -131,10 +133,11 @@ void GpgFrontend::GpgCommandExecutor::Execute( data_object->AppendObject(std::move(callback)); data_object->AppendObject(std::move(interact_func)); data_object->AppendObject(std::move(arguments)); - data_object->AppendObject(std::move(cmd)); + data_object->AppendObject(std::move(std::string{cmd})); auto *process_task = new GpgFrontend::Thread::Task( - std::move(runner), std::move(result_callback), data_object); + std::move(runner), fmt::format("Execute/{}", cmd), data_object, + std::move(result_callback)); QEventLoop looper; QObject::connect(process_task, &Thread::Task::SignalTaskFinished, &looper, @@ -148,3 +151,112 @@ void GpgFrontend::GpgCommandExecutor::Execute( // this is to keep reference vaild until task finished looper.exec(); } + +void GpgFrontend::GpgCommandExecutor::ExecuteConcurrently( + std::string cmd, std::vector<std::string> arguments, + std::function<void(int, std::string, std::string)> callback, + std::function<void(QProcess *)> interact_func) { + SPDLOG_DEBUG("called cmd {} arguments size: {}", cmd, arguments.size()); + + Thread::Task::TaskCallback result_callback = + [](int rtn, Thread::Task::DataObjectPtr data_object) { + if (data_object->GetObjectSize() != 4) + throw std::runtime_error("invalid data object size"); + + auto exit_code = data_object->PopObject<int>(); + auto process_stdout = data_object->PopObject<std::string>(); + auto process_stderr = data_object->PopObject<std::string>(); + auto callback = data_object->PopObject< + std::function<void(int, std::string, std::string)>>(); + + // call callback + callback(exit_code, process_stdout, process_stderr); + }; + + Thread::Task::TaskRunnable runner = + [](GpgFrontend::Thread::Task::DataObjectPtr data_object) -> int { + SPDLOG_DEBUG("process runner called, data object size: {}", + data_object->GetObjectSize()); + + if (data_object->GetObjectSize() != 4) + throw std::runtime_error("invalid data object size"); + + // get arguments + auto cmd = data_object->PopObject<std::string>(); + auto arguments = data_object->PopObject<std::vector<std::string>>(); + auto interact_func = + data_object->PopObject<std::function<void(QProcess *)>>(); + + auto *cmd_process = new QProcess(); + cmd_process->setProcessChannelMode(QProcess::MergedChannels); + + QObject::connect(cmd_process, &QProcess::started, + []() -> void { SPDLOG_DEBUG("process started"); }); + QObject::connect( + cmd_process, &QProcess::readyReadStandardOutput, + [interact_func, cmd_process]() { interact_func(cmd_process); }); + QObject::connect(cmd_process, &QProcess::errorOccurred, + [=](QProcess::ProcessError error) { + SPDLOG_ERROR("error in executing command: {} error: {}", + cmd, error); + }); + QObject::connect( + cmd_process, qOverload<int, QProcess::ExitStatus>(&QProcess::finished), + [=](int, QProcess::ExitStatus status) { + if (status == QProcess::NormalExit) + SPDLOG_DEBUG( + "proceess finished, succeed in executing command: {}, exit " + "status: {}", + cmd, status); + else + SPDLOG_ERROR( + "proceess finished, error in executing command: {}, exit " + "status: {}", + cmd, status); + }); + + cmd_process->setProgram(QString::fromStdString(cmd)); + + QStringList q_arguments; + for (const auto &argument : arguments) + q_arguments.append(QString::fromStdString(argument)); + cmd_process->setArguments(q_arguments); + + SPDLOG_DEBUG("process start ready, cmd: {} {}", cmd, + q_arguments.join(" ").toStdString()); + + cmd_process->start(); + cmd_process->waitForFinished(); + + std::string process_stdout = + cmd_process->readAllStandardOutput().toStdString(), + process_stderr = + cmd_process->readAllStandardError().toStdString(); + int exit_code = cmd_process->exitCode(); + + cmd_process->close(); + cmd_process->deleteLater(); + + // transfer result + data_object->AppendObject(std::move(process_stderr)); + data_object->AppendObject(std::move(process_stdout)); + data_object->AppendObject(std::move(exit_code)); + + return 0; + }; + + // data transfer into task + auto data_object = std::make_shared<Thread::Task::DataObject>(); + data_object->AppendObject(std::move(callback)); + data_object->AppendObject(std::move(interact_func)); + data_object->AppendObject(std::move(arguments)); + data_object->AppendObject(std::move(std::string{cmd})); + + auto *process_task = new GpgFrontend::Thread::Task( + std::move(runner), fmt::format("ExecuteConcurrently/{}", cmd), + data_object, std::move(result_callback), false); + + GpgFrontend::Thread::TaskRunnerGetter::GetInstance() + .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_External_Process) + ->PostTask(process_task); +} diff --git a/src/core/function/gpg/GpgCommandExecutor.h b/src/core/function/gpg/GpgCommandExecutor.h index c597feac..da0e7a8b 100644 --- a/src/core/function/gpg/GpgCommandExecutor.h +++ b/src/core/function/gpg/GpgCommandExecutor.h @@ -55,7 +55,7 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor int channel = SingletonFunctionObject::GetDefaultChannel()); /** - * @brief Excuting an order + * @brief Excuting a command * * @param arguments Command parameters * @param interact_func Command answering function @@ -66,6 +66,11 @@ class GPGFRONTEND_CORE_EXPORT GpgCommandExecutor [](int, std::string, std::string) {}, std::function<void(QProcess *)> interact_func = [](QProcess *) {}); + void ExecuteConcurrently( + std::string cmd, std::vector<std::string> arguments, + std::function<void(int, std::string, std::string)> callback, + std::function<void(QProcess *)> interact_func = [](QProcess *) {}); + private: GpgContext &ctx_ = GpgContext::GetInstance( SingletonFunctionObject::GetChannel()); ///< Corresponding context diff --git a/src/core/thread/CtxCheckTask.cpp b/src/core/thread/CtxCheckTask.cpp index 997dd341..eef05b1b 100644 --- a/src/core/thread/CtxCheckTask.cpp +++ b/src/core/thread/CtxCheckTask.cpp @@ -30,8 +30,9 @@ #include "core/GpgCoreInit.h" #include "core/common/CoreCommonUtil.h" #include "core/function/gpg/GpgKeyGetter.h" +#include "thread/Task.h" -GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() { +GpgFrontend::Thread::CtxCheckTask::CtxCheckTask() : Task("ctx_check_task") { connect(this, &CtxCheckTask::SignalGnupgNotInstall, CoreCommonUtil::GetInstance(), &CoreCommonUtil::SignalGnupgNotInstall); diff --git a/src/core/thread/FileReadTask.cpp b/src/core/thread/FileReadTask.cpp index 0f7d11c3..0888e029 100644 --- a/src/core/thread/FileReadTask.cpp +++ b/src/core/thread/FileReadTask.cpp @@ -28,7 +28,7 @@ namespace GpgFrontend::UI { -FileReadTask::FileReadTask(std::string path) { +FileReadTask::FileReadTask(std::string path) : Task("file_read_task") { connect(this, &FileReadTask::SignalFileBytesReadNext, this, &FileReadTask::read_bytes); diff --git a/src/core/thread/Task.cpp b/src/core/thread/Task.cpp index 87be7a10..823276ae 100644 --- a/src/core/thread/Task.cpp +++ b/src/core/thread/Task.cpp @@ -35,39 +35,61 @@ #include "core/thread/TaskRunner.h" -GpgFrontend::Thread::Task::Task() : uuid_(generate_uuid()) { - SPDLOG_TRACE("task {} created", uuid_); +const std::string GpgFrontend::Thread::Task::DEFAULT_TASK_NAME = "default-task"; + +GpgFrontend::Thread::Task::Task(std::string name) + : uuid_(generate_uuid()), name_(name) { + SPDLOG_TRACE("task {}/ created", GetFullID()); init(); } -GpgFrontend::Thread::Task::Task(TaskCallback callback, - DataObjectPtr data_object) +GpgFrontend::Thread::Task::Task(TaskRunnable runnable, std::string name, + DataObjectPtr data_object, bool sequency) : uuid_(generate_uuid()), - callback_(std::move(callback)), + name_(name), + runnable_(std::move(runnable)), + callback_(std::move([](int, const std::shared_ptr<DataObject> &) {})), callback_thread_(QThread::currentThread()), - data_object_(data_object) { - SPDLOG_TRACE("task {} created with callback, callback_thread_: {}", uuid_, - static_cast<void *>(callback_thread_)); + data_object_(data_object), + sequency_(sequency) { + SPDLOG_TRACE("task {} created with runnable, callback_thread_: {}", + GetFullID(), static_cast<void *>(callback_thread_)); init(); } -GpgFrontend::Thread::Task::Task(TaskRunnable runnable, TaskCallback callback, - DataObjectPtr data_object) +GpgFrontend::Thread::Task::Task(TaskRunnable runnable, std::string name, + DataObjectPtr data_object, + TaskCallback callback, bool sequency) : uuid_(generate_uuid()), + name_(name), runnable_(std::move(runnable)), callback_(std::move(callback)), callback_thread_(QThread::currentThread()), - data_object_(data_object) { + data_object_(data_object), + sequency_(sequency) { init(); SPDLOG_TRACE( - "task {} created with runnable and callback, callback_thread_: {}", uuid_, - static_cast<void *>(callback_thread_)); + "task {} created with runnable and callback, callback_thread_: {}", + GetFullID(), static_cast<void *>(callback_thread_)); +} + +GpgFrontend::Thread::Task::~Task() { + SPDLOG_TRACE("task {} destroyed", GetFullID()); } -GpgFrontend::Thread::Task::~Task() { SPDLOG_TRACE("task {} destroyed", uuid_); } +/** + * @brief + * + * @return std::string + */ +std::string GpgFrontend::Thread::Task::GetFullID() const { + return uuid_ + "/" + name_; +} std::string GpgFrontend::Thread::Task::GetUUID() const { return uuid_; } +bool GpgFrontend::Thread::Task::GetSequency() const { return sequency_; } + void GpgFrontend::Thread::Task::SetFinishAfterRun(bool finish_after_run) { this->finish_after_run_ = finish_after_run; } @@ -79,7 +101,7 @@ void GpgFrontend::Thread::Task::init() { } void GpgFrontend::Thread::Task::before_finish_task() { - SPDLOG_TRACE("task {} finished", uuid_); + SPDLOG_TRACE("task {} finished", GetFullID()); try { if (callback_) { @@ -101,7 +123,7 @@ void GpgFrontend::Thread::Task::before_finish_task() { } void GpgFrontend::Thread::Task::run() { - SPDLOG_TRACE("task {} started", uuid_); + SPDLOG_TRACE("task {} started", GetFullID()); Run(); if (finish_after_run_) emit SignalTaskFinished(); } diff --git a/src/core/thread/Task.h b/src/core/thread/Task.h index d9a70618..d239cfee 100644 --- a/src/core/thread/Task.h +++ b/src/core/thread/Task.h @@ -50,6 +50,8 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { using TaskRunnable = std::function<int(DataObjectPtr)>; ///< using TaskCallback = std::function<void(int, DataObjectPtr)>; ///< + static const std::string DEFAULT_TASK_NAME; + friend class TaskRunner; /** @@ -164,14 +166,15 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { * @brief Construct a new Task object * */ - Task(); + Task(std::string name = DEFAULT_TASK_NAME); /** * @brief Construct a new Task object * * @param callback The callback function to be executed. */ - explicit Task(TaskCallback callback, DataObjectPtr data_object = nullptr); + explicit Task(TaskRunnable runnable, std::string name = DEFAULT_TASK_NAME, + DataObjectPtr data_object = nullptr, bool sequency = true); /** * @brief Construct a new Task object @@ -179,9 +182,9 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { * @param runnable */ explicit Task( - TaskRunnable runnable, + TaskRunnable runnable, std::string name, DataObjectPtr data, TaskCallback callback = [](int, const std::shared_ptr<DataObject> &) {}, - DataObjectPtr data = nullptr); + bool sequency = true); /** * @brief Destroy the Task object @@ -202,6 +205,20 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { */ std::string GetUUID() const; + /** + * @brief + * + * @return std::string + */ + std::string GetFullID() const; + + /** + * @brief + * + * @return std::string + */ + bool GetSequency() const; + signals: /** * @brief @@ -232,6 +249,8 @@ class GPGFRONTEND_CORE_EXPORT Task : public QObject, public QRunnable { private: const std::string uuid_; + const std::string name_; + const bool sequency_ = true; ///< must run in the same thread TaskCallback callback_; ///< TaskRunnable runnable_; ///< bool finish_after_run_ = true; ///< diff --git a/src/core/thread/TaskRunner.cpp b/src/core/thread/TaskRunner.cpp index dc6ac385..29aad68b 100644 --- a/src/core/thread/TaskRunner.cpp +++ b/src/core/thread/TaskRunner.cpp @@ -34,23 +34,29 @@ GpgFrontend::Thread::TaskRunner::TaskRunner() = default; GpgFrontend::Thread::TaskRunner::~TaskRunner() = default; void GpgFrontend::Thread::TaskRunner::PostTask(Task* task) { - if (task == nullptr) return; + if (task == nullptr) { + SPDLOG_ERROR("task posted is null"); + return; + } - std::string uuid = task->GetUUID(); - SPDLOG_TRACE("post task: {}", uuid); + SPDLOG_TRACE("post task: {}", task->GetFullID()); task->setParent(nullptr); task->moveToThread(this); - connect(task, &Task::SignalTaskPostFinishedDone, this, [&, uuid]() { - auto it = pending_tasks_.find(uuid); - if (it == pending_tasks_.end()) { + connect(task, &Task::SignalTaskPostFinishedDone, this, [&, this, task]() { + SPDLOG_DEBUG("cleaning task {}", task->GetFullID()); + auto pending_task = pending_tasks_.find(task->GetUUID()); + if (pending_task == pending_tasks_.end()) { + SPDLOG_ERROR("cannot find task in pending list: {}", task->GetFullID()); return; } else { - it->second->deleteLater(); - pending_tasks_.erase(it); + std::lock_guard<std::mutex> lock(tasks_mutex_); + pending_tasks_.erase(pending_task); } + task->deleteLater(); }); + { std::lock_guard<std::mutex> lock(tasks_mutex_); tasks.push(task); @@ -83,24 +89,29 @@ void GpgFrontend::Thread::TaskRunner::PostScheduleTask(Task* task, } if (task != nullptr) { - // Run the task - SPDLOG_TRACE("task runner: running task {}", task->GetUUID()); try { - task->run(); + // Run the task + SPDLOG_TRACE("task runner: running task {}, sequency: {}", + task->GetFullID(), task->GetSequency()); + if (task->GetSequency()) { + // run sequently + task->run(); + } else { + // run concurrently + thread_pool_.start(task); + } } catch (const std::exception& e) { SPDLOG_ERROR("task runner: exception in task {}, exception: {}", - task->GetUUID(), e.what()); - + task->GetFullID(), e.what()); // destroy the task, remove the task from the pending tasks - task->deleteLater(); pending_tasks_.erase(task->GetUUID()); + task->deleteLater(); } catch (...) { SPDLOG_ERROR("task runner: unknown exception in task: {}", - task->GetUUID()); - + task->GetFullID()); // destroy the task, remove the task from the pending tasks - task->deleteLater(); pending_tasks_.erase(task->GetUUID()); + task->deleteLater(); } } } diff --git a/src/core/thread/TaskRunner.h b/src/core/thread/TaskRunner.h index 6a5e00a5..fff5c368 100644 --- a/src/core/thread/TaskRunner.h +++ b/src/core/thread/TaskRunner.h @@ -79,6 +79,7 @@ class GPGFRONTEND_CORE_EXPORT TaskRunner : public QThread { std::queue<Task*> tasks; ///< The task queue std::map<std::string, Task*> pending_tasks_; ///< The pending tasks std::mutex tasks_mutex_; ///< The task queue mutex + QThreadPool thread_pool_{this}; ///< run non-sequency task }; } // namespace GpgFrontend::Thread diff --git a/src/ui/UserInterfaceUtils.cpp b/src/ui/UserInterfaceUtils.cpp index 408a1c04..6c3b0726 100644 --- a/src/ui/UserInterfaceUtils.cpp +++ b/src/ui/UserInterfaceUtils.cpp @@ -120,8 +120,8 @@ void process_operation(QWidget *parent, const std::string &waiting_title, auto *dialog = new WaitingDialog(QString::fromStdString(waiting_title), parent); - auto *process_task = - new Thread::Task(std::move(func), std::move(callback), data_object); + auto *process_task = new Thread::Task(std::move(func), waiting_title, + data_object, std::move(callback)); QApplication::connect(process_task, &Thread::Task::SignalTaskFinished, dialog, &QDialog::close); @@ -398,13 +398,15 @@ void CommonUtils::SlotImportKeyFromKeyServer( } void CommonUtils::slot_update_key_status() { - auto refresh_task = new Thread::Task([](Thread::Task::DataObjectPtr) -> int { - // flush key cache for all GpgKeyGetter Intances. - for (const auto &channel_id : GpgKeyGetter::GetAllChannelId()) { - GpgKeyGetter::GetInstance(channel_id).FlushKeyCache(); - } - return 0; - }); + auto refresh_task = new Thread::Task( + [](Thread::Task::DataObjectPtr) -> int { + // flush key cache for all GpgKeyGetter Intances. + for (const auto &channel_id : GpgKeyGetter::GetAllChannelId()) { + GpgKeyGetter::GetInstance(channel_id).FlushKeyCache(); + } + return 0; + }, + "update_key_status_task"); connect(refresh_task, &Thread::Task::SignalTaskFinished, this, &CommonUtils::SignalKeyDatabaseRefreshDone); @@ -419,7 +421,7 @@ void CommonUtils::slot_popup_passphrase_input_dialog() { dialog->setWindowTitle(_("Password Input Dialog")); dialog->setInputMode(QInputDialog::TextInput); dialog->setTextEchoMode(QLineEdit::Password); - dialog->setLabelText("Please Input The Password"); + dialog->setLabelText(_("Please Input The Password")); dialog->resize(500, 80); dialog->exec(); diff --git a/src/ui/dialog/help/GnupgTab.cpp b/src/ui/dialog/help/GnupgTab.cpp index 92c3fd55..5d84ec65 100644 --- a/src/ui/dialog/help/GnupgTab.cpp +++ b/src/ui/dialog/help/GnupgTab.cpp @@ -31,14 +31,13 @@ #include "GnupgTab.h" +#include <shared_mutex> + #include "ui/UserInterfaceUtils.h" #include "ui_GnuPGInfo.h" GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) : QWidget(parent), ui_(std::make_shared<Ui_GnuPGInfo>()) { - GpgContext& ctx = GpgContext::GetInstance(); - auto info = ctx.GetInfo(false); - ui_->setupUi(this); QStringList components_column_titles; @@ -77,7 +76,7 @@ GpgFrontend::UI::GnupgTab::GnupgTab(QWidget* parent) } void GpgFrontend::UI::GnupgTab::process_software_info() { - auto ctx_info = GpgContext::GetInstance().GetInfo(true); + auto& ctx_info = GpgContext::GetInstance().GetInfo(true); ui_->gnupgVersionLabel->setText(QString::fromStdString( fmt::format("Version: {}", ctx_info.GnupgVersion))); diff --git a/src/ui/thread/KeyServerImportTask.cpp b/src/ui/thread/KeyServerImportTask.cpp index bf3e1822..b02a4487 100644 --- a/src/ui/thread/KeyServerImportTask.cpp +++ b/src/ui/thread/KeyServerImportTask.cpp @@ -30,7 +30,8 @@ GpgFrontend::UI::KeyServerImportTask::KeyServerImportTask( std::string keyserver_url, std::vector<std::string> keyids) - : keyserver_url_(std::move(keyserver_url)), + : Task("key_server_import_task"), + keyserver_url_(std::move(keyserver_url)), keyids_(std::move(keyids)), manager_(new QNetworkAccessManager(this)) {} diff --git a/src/ui/thread/KeyServerSearchTask.cpp b/src/ui/thread/KeyServerSearchTask.cpp index 0090e79d..1f90565f 100644 --- a/src/ui/thread/KeyServerSearchTask.cpp +++ b/src/ui/thread/KeyServerSearchTask.cpp @@ -30,7 +30,8 @@ GpgFrontend::UI::KeyServerSearchTask::KeyServerSearchTask( std::string keyserver_url, std::string search_string) - : keyserver_url_(std::move(keyserver_url)), + : Task("key_server_search_task"), + keyserver_url_(std::move(keyserver_url)), search_string_(std::move(search_string)), manager_(new QNetworkAccessManager(this)) {} diff --git a/src/ui/thread/ListedKeyServerTestTask.cpp b/src/ui/thread/ListedKeyServerTestTask.cpp index 17bb0356..fe87ed06 100644 --- a/src/ui/thread/ListedKeyServerTestTask.cpp +++ b/src/ui/thread/ListedKeyServerTestTask.cpp @@ -30,7 +30,8 @@ GpgFrontend::UI::ListedKeyServerTestTask::ListedKeyServerTestTask( const QStringList& urls, int timeout, QWidget* parent) - : urls_(urls), + : Task("listed_key_server_test_task"), + urls_(urls), timeout_(timeout), network_manager_(new QNetworkAccessManager(this)), result_(urls_.size(), kTestResultType_Error) { diff --git a/src/ui/thread/VersionCheckTask.cpp b/src/ui/thread/VersionCheckTask.cpp index 45fe8c80..08571223 100644 --- a/src/ui/thread/VersionCheckTask.cpp +++ b/src/ui/thread/VersionCheckTask.cpp @@ -36,7 +36,8 @@ namespace GpgFrontend::UI { VersionCheckTask::VersionCheckTask() - : network_manager_(new QNetworkAccessManager(this)), + : Task("version_check_task"), + network_manager_(new QNetworkAccessManager(this)), current_version_(std::string("v") + std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR) + "." + std::to_string(VERSION_PATCH)) { |