From: Hwankyu Jhun Date: Thu, 1 Jun 2023 07:34:05 +0000 (+0000) Subject: Block and unblock threads X-Git-Tag: accepted/tizen/unified/20230605.170333~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6df8fc067760f6ad140c50adfaba3db9fcbf65c1;p=platform%2Fcore%2Fappfw%2Flaunchpad.git Block and unblock threads Before calling the security_manager_prepare_app2() function, all threads of the loader process MUST be blocked not to make a new thread or terminate itself. This patch blocks all sub threads using real-time signal and condition variable. After calling the function, the main thread of the loade process sends the signal to unblock all sub threads using condition variable. Change-Id: I60e0e102f62fe8327fa844072b3017075e1692fa Signed-off-by: Hwankyu Jhun --- diff --git a/src/lib/launchpad/step_prepare_execution.cc b/src/lib/launchpad/step_prepare_execution.cc index 144a0869..ad8481a4 100644 --- a/src/lib/launchpad/step_prepare_execution.cc +++ b/src/lib/launchpad/step_prepare_execution.cc @@ -33,6 +33,7 @@ #include "common/inc/launchpad_common.h" #include "common/inc/launchpad_types.h" #include "launchpad/log_private.hh" +#include "launchpad/thread_control.hh" namespace launchpad { @@ -112,10 +113,12 @@ int StepPrepareExecution::MountResourceDirectories(AppInfo* app_info) { int StepPrepareExecution::SecurityManagerPrepareApp(AppInfo* app_info) { auto* enabled_light_user = bundle_get_val(app_info->GetBundle().GetHandle(), kAulEnabledLightUser); + ThreadControl::GetInst().BlockThreads(); _W("security_manager_prepare_app2() ++ %s", app_info->GetAppId().c_str()); int ret = security_manager_prepare_app2(app_info->GetAppId().c_str(), enabled_light_user); _W("security_manager_prepare_app2() -- %s", app_info->GetAppId().c_str()); + ThreadControl::GetInst().UnblockThreads(); if (ret != SECURITY_MANAGER_SUCCESS) { _E("security_manager_prepare_app2() is failed. appid: %s, error: %d", app_info->GetAppId().c_str(), ret); diff --git a/src/lib/launchpad/thread_control.cc b/src/lib/launchpad/thread_control.cc index 2f36b08d..62f6f26c 100644 --- a/src/lib/launchpad/thread_control.cc +++ b/src/lib/launchpad/thread_control.cc @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -47,6 +48,38 @@ std::vector GetTasks() { return tasks; } +std::string GetThreadName(pid_t tid) { + std::string path = "/proc/" + std::to_string(tid) + "/comm"; + std::ifstream proc_file(path); + if (proc_file.is_open()) { + std::string name; + std::getline(proc_file, name); + proc_file.close(); + return name; + } + + _E("Failed to read name. tid(%d)", tid); + return ""; +} + +int GetThreadCountWithoutGmain(const std::vector& tasks) { + int count = tasks.size() - 1; + for (auto tid : tasks) { + if (getpid() != tid) { + // Unfortunately, the signal handler of the gmain thread is not invoked. + // The gmain thread always calls poll(). + // To avoid delay issue of calling usleep(), this function decreases + // the count if the gmain threads exists. + if (GetThreadName(tid) == "gmain") { + _W("%d is gmain thread", tid); + count--; + } + } + } + + return count; +} + } // namespace ThreadControl& ThreadControl::GetInst() { @@ -108,7 +141,7 @@ bool ThreadControl::ChangeSigaction() { void ThreadControl::InterruptThreads() { pid_t pid = getpid(); auto tasks = GetTasks(); - count_ = tasks.size() - 1; + count_ = GetThreadCountWithoutGmain(tasks); _D("tasks count: %d", count_); for (auto& tid : tasks) { if (tid != pid) { @@ -123,7 +156,7 @@ void ThreadControl::InterruptThreads() { void ThreadControl::ContinueThreads() { std::unique_lock lock(mutex_); - count_ = GetTasks().size() - 1; + count_ = GetThreadCountWithoutGmain(GetTasks()); _D("tasks count: %d", count_); done_ = true; cond_.notify_all(); @@ -140,13 +173,13 @@ void ThreadControl::RestoreSigaction() { } void ThreadControl::SignalHandler(int signo) { - _W("Block"); + _D("Block"); auto& inst = ThreadControl::GetInst(); std::unique_lock lock(inst.mutex_); inst.count_--; inst.cond_.wait(lock, [&] { return inst.done_; }); inst.count_--; - _W("Unblock"); + _D("Unblock"); } } // namespace launchpad