Modify thread control
[platform/core/appfw/launchpad.git] / src / lib / launchpad / thread_control.cc
index 2f36b08..680b305 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") {
+        _D("%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,16 @@ 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_; });
+  if (inst.cond_.wait_for(lock, std::chrono::seconds(5),
+                          [&] { return inst.done_; }))
+    _D("Unblock");
+  else
+    _E("Timed out");
   inst.count_--;
-  _W("Unblock");
 }
 
 }  // namespace launchpad