Block and unblock threads 33/293633/2
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 1 Jun 2023 07:34:05 +0000 (07:34 +0000)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 1 Jun 2023 07:43:30 +0000 (07:43 +0000)
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 <h.jhun@samsung.com>
src/lib/launchpad/step_prepare_execution.cc
src/lib/launchpad/thread_control.cc

index 144a08691415fd26576b9a396809587c13eeb089..ad8481a4de9756dcb66d63fefcdb119d5edf78a2 100644 (file)
@@ -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);
index 2f36b08d6a3f1e5e645bd07bf09d9502ef7e808e..62f6f26ca776e30908753562f0428097cb342e02 100644 (file)
@@ -20,6 +20,7 @@
 #include <unistd.h>
 
 #include <filesystem>
+#include <fstream>
 #include <string>
 #include <vector>
 
@@ -47,6 +48,38 @@ std::vector<pid_t> 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<pid_t>& 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<std::mutex> 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<std::mutex> lock(inst.mutex_);
   inst.count_--;
   inst.cond_.wait(lock, [&] { return inst.done_; });
   inst.count_--;
-  _W("Unblock");
+  _D("Unblock");
 }
 
 }  // namespace launchpad