From f85766b27ea8970bc82308e0baec47ce374f7434 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 13 Mar 2023 23:29:31 +0000 Subject: [PATCH] Refactor launchpad worker The launchpad worker is implemented using C++ language. Change-Id: Ida9775036924f4e148ba5896433634fa20f52d5f Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 90 ++++--------- src/launchpad-process-pool/launchpad_signal.cc | 141 +++++++++---------- src/launchpad-process-pool/launchpad_worker.cc | 180 ------------------------- src/launchpad-process-pool/launchpad_worker.h | 40 ------ src/launchpad-process-pool/worker.cc | 80 +++++++++++ src/launchpad-process-pool/worker.hh | 55 ++++++++ 6 files changed, 225 insertions(+), 361 deletions(-) delete mode 100644 src/launchpad-process-pool/launchpad_worker.cc delete mode 100644 src/launchpad-process-pool/launchpad_worker.h create mode 100644 src/launchpad-process-pool/worker.cc create mode 100644 src/launchpad-process-pool/worker.hh diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 9917e05..92d24f6 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -39,6 +39,7 @@ #include #include +#include #include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/launcher_info.hh" @@ -48,7 +49,6 @@ #include "launchpad-process-pool/launchpad_io_channel.h" #include "launchpad-process-pool/launchpad_memory_monitor.h" #include "launchpad-process-pool/launchpad_signal.h" -#include "launchpad-process-pool/launchpad_worker.h" #include "launchpad-process-pool/loader_info.hh" #include "launchpad-process-pool/slot_info.h" #include "lib/common/inc/key.h" @@ -60,6 +60,7 @@ #include "launchpad-process-pool/dbus.hh" #include "launchpad-process-pool/log.hh" +#include "launchpad-process-pool/worker.hh" #define AUL_PR_NAME 16 #define EXEC_CANDIDATE_EXPIRED 5 @@ -201,6 +202,22 @@ typedef int (*request_handler)(request_h request); namespace { +class CleanupInfo : public launchpad::Worker::Job { + public: + CleanupInfo(std::string appid, pid_t pid) + : appid_(std::move(appid)), pid_(pid) {} + + void Do() override { + _W("security_manager_cleanup_app() ++"); + security_manager_cleanup_app(appid_.c_str(), getuid(), pid_); + _W("security_manager_cleanup_app() --"); + } + + private: + std::string appid_; + pid_t pid_; +}; + int __sys_hwacc; std::unique_ptr loader_info_manager; std::unique_ptr app_defined_loader_info_manager; @@ -220,8 +237,8 @@ io_channel_h __logger_channel; io_channel_h __label_monitor_channel; io_channel_h __launchpad_channel; int __client_fd = -1; -worker_h __cleaner; launchpad::AsanAppChecker __asan_app_checker; +std::unique_ptr cleaner; } // namespace @@ -1623,71 +1640,16 @@ static bool __handle_hydra_event(int fd, io_condition_e cond, void* data) { return true; } -static void __destroy_cleanup_info(struct cleanup_info_s* info) { - if (!info) - return; - - free(info->appid); - free(info); -} - -static struct cleanup_info_s* __create_cleanup_info(const char* appid, - int pid) { - struct cleanup_info_s* info; - - info = static_cast(malloc(sizeof(struct cleanup_info_s))); - if (!info) { - _E("Out of memory"); - return nullptr; - } - - info->appid = strdup(appid); - if (!info->appid) { - _E("strdup(%s) is failed", appid); - __destroy_cleanup_info(info); - return nullptr; - } - - info->pid = pid; - - return info; -} - -static bool __cleanup_app_cb(void* user_data) { - struct cleanup_info_s* info = (struct cleanup_info_s*)user_data; - - _W("security_manager_cleanup_app() ++"); - security_manager_cleanup_app(info->appid, getuid(), info->pid); - _W("security_manager_cleanup_app() --"); - __destroy_cleanup_info(info); - return false; -} - static void __handle_sigchild(int pid, void* user_data) { - candidate_process_context_t* cpc; - struct cleanup_info_s* info; - char* appid; - int ret = -1; - - appid = static_cast( + char* appid = static_cast( g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid))); if (appid) { - info = __create_cleanup_info(appid, pid); - if (info) - ret = _worker_add_job(__cleaner, __cleanup_app_cb, info); - - if (ret != 0) { - __destroy_cleanup_info(info); - _W("security_manager_cleanup_app() ++"); - security_manager_cleanup_app(appid, getuid(), pid); - _W("security_manager_cleanup_app() --"); - } - + cleaner->Add(std::make_shared(appid, pid)); g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid)); } launchpad::Log::Print("[SIGCHLD]", "pid(%7d)", pid); - cpc = __find_slot_from_pid(pid); + candidate_process_context_t* cpc = __find_slot_from_pid(pid); if (cpc != nullptr) { cpc->pid = CANDIDATE_NONE; __dispose_candidate_process(cpc); @@ -3420,23 +3382,19 @@ static int __before_loop(int argc, char** argv) { return -1; } - ret = _worker_create("cleaner+", &__cleaner); - if (ret < 0) - return ret; - __register_vconf_events(); __init_app_defined_loader_monitor(); + cleaner.reset(new launchpad::Worker("cleaner+")); launchpad::Log::Init(); _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__); - return 0; } static void __after_loop(void) { launchpad::Log::Finish(); + cleaner.reset(); _memory_monitor_fini(); __unregister_vconf_events(); - _worker_destroy(__cleaner); if (__pid_table) g_hash_table_destroy(__pid_table); diff --git a/src/launchpad-process-pool/launchpad_signal.cc b/src/launchpad-process-pool/launchpad_signal.cc index d08313b..13b6a0a 100644 --- a/src/launchpad-process-pool/launchpad_signal.cc +++ b/src/launchpad-process-pool/launchpad_signal.cc @@ -26,22 +26,83 @@ #include #include +#include +#include #include #include #include "launchpad-process-pool/launchpad_io_channel.h" -#include "launchpad-process-pool/launchpad_worker.h" #include "lib/common/inc/launchpad_common.h" #include "lib/common/inc/launchpad_proc.h" #include "lib/common/inc/launchpad_socket.h" #include "lib/common/inc/log_private.h" #include "launchpad-process-pool/dbus.hh" +#include "launchpad-process-pool/log_private.hh" +#include "launchpad-process-pool/worker.hh" + +namespace fs = std::filesystem; namespace { constexpr const char HYDRA_SIGCHLD_SOCK[] = ".hydra-sigchld-sock"; +class GarbageCollector : public launchpad::Worker::Job { + public: + explicit GarbageCollector(pid_t pid) : pid_(pid) {} + + void Do() override { + _W("pid: %d", pid_); + _delete_sock_path(pid_, getuid()); + DeleteUnusedFiles(); + SocketGarbadgeCollector(); + } + + private: + void SocketGarbadgeCollector() { + std::string path = "/run/aul/apps/" + std::to_string(getuid()); + for (const auto &entry : fs::directory_iterator(path)) { + if (!isdigit(entry.path().filename().string()[0])) + continue; + + std::string proc_path = "/proc/" + entry.path().filename().string(); + if (access(proc_path.c_str(), F_OK) < 0) { + _delete_sock_path(atoi(entry.path().filename().string().c_str()), + getuid()); + } + } + } + + void DeleteUnusedFiles() { + std::vector files = { + "clr-debug-pipe-" + std::to_string(pid_) + "-", + "dotnet-diagnostic-" + std::to_string(pid_) + "-" + }; + + fs::path tmp_path = "/tmp"; + for (const auto &entry : fs::directory_iterator(tmp_path)) { + if (entry.is_directory() || entry.path().filename().string()[0] == '.') + continue; + + bool found = false; + for (const auto &file : files) { + if (entry.path().filename().string().find(file) == 0) { + fs::remove(entry.path()); + _W("Removed file: %s", entry.path().c_str()); + found = true; + break; + } + } + + if (!found) + continue; + } + } + + private: + pid_t pid_; +}; + pid_t __pid; sigset_t __mask; sigset_t __old_mask; @@ -52,79 +113,16 @@ io_channel_h __hydra_sigchld_channel; signal_sigchld_cb __callback; void* __user_data; -worker_h recycle_bin; +std::unique_ptr recycle_bin; } // namespace static gboolean __hydra_sigchld_recovery_cb(gpointer data); static gboolean __sigchld_recovery_cb(gpointer data); -static void __socket_garbage_collector(void) { - DIR* dp; - struct dirent* dentry = nullptr; - char path[PATH_MAX]; - - snprintf(path, sizeof(path), "/run/aul/apps/%d", getuid()); - dp = opendir(path); - if (!dp) - return; - - while ((dentry = readdir(dp)) != nullptr) { - if (!isdigit(dentry->d_name[0])) - continue; - - snprintf(path, sizeof(path), "/proc/%s", dentry->d_name); - if (access(path, F_OK) < 0) - _delete_sock_path(atoi(dentry->d_name), getuid()); - } - closedir(dp); -} - -static void __delete_unused_files(pid_t pid) { - std::vector files = { - "clr-debug-pipe-" + std::to_string(pid) + "-", - "dotnet-diagnostic-" + std::to_string(pid) + "-" - }; - - DIR* dp = opendir("/tmp"); - if (dp == nullptr) { - _E("opendir() is failed"); - return; - } - - struct dirent* dentry = nullptr; - while ((dentry = readdir(dp)) != nullptr) { - if (dentry->d_name[0] == '.') - continue; - - if (dentry->d_name[0] != 'c' && dentry->d_name[0] != 'd') - continue; - - for (size_t i = 0; i < files.size(); ++i) { - if (files[i].compare(0, files[i].length(), dentry->d_name, 0, - files[i].length()) == 0) { - std::string path = std::string("/tmp/") + dentry->d_name; - unlink(path.c_str()); - _W("unlink(%s)", path.c_str()); - } - } - } - closedir(dp); -} - -static bool __garbage_collector(void *user_data) { - pid_t pid = GPOINTER_TO_INT( - reinterpret_cast(user_data) & UINT32_MAX); - _W("pid(%d)", pid); - _delete_sock_path(pid, getuid()); - __delete_unused_files(pid); - __socket_garbage_collector(); - return false; -} - static void __sigchld_action(int pid) { launchpad::DBus::SendAppDeadSignal(pid); - _worker_add_job(recycle_bin, __garbage_collector, GINT_TO_POINTER(pid)); + recycle_bin->Add(std::make_shared(pid)); } static int __check_permission(int pid) { @@ -429,12 +427,7 @@ int _signal_init(void) { } } - ret = _worker_create("RecycleBin+", &recycle_bin); - if (ret < 0) { - _E("_worker_create() is failed"); - return ret; - } - + recycle_bin.reset(new launchpad::Worker("RecycleBin+")); return 0; } @@ -447,9 +440,7 @@ void _signal_fini(void) { #endif _D("SIGNAL_FINI"); - if (getpid() == __pid) - _worker_destroy(recycle_bin); - + recycle_bin.reset(); _signal_set_sigchld_cb(nullptr, nullptr); __hydra_sigchld_fini(); __sigchld_fini(); diff --git a/src/launchpad-process-pool/launchpad_worker.cc b/src/launchpad-process-pool/launchpad_worker.cc deleted file mode 100644 index 4729e48..0000000 --- a/src/launchpad-process-pool/launchpad_worker.cc +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "launchpad-process-pool/launchpad_worker.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lib/common/inc/log_private.h" - -struct job_s { - worker_job_cb callback; - void* user_data; -}; - -struct worker_s { - char* name; - GThread* thread; - GMutex mutex; - GCond cond; - GQueue* queue; -}; - -int _worker_add_job(worker_h worker, worker_job_cb callback, void* user_data) { - struct job_s* job; - - if (!worker || !callback) { - _E("Invalid parameter"); - return -EINVAL; - } - - job = static_cast(malloc(sizeof(job_s))); - if (!job) { - _E("Out of memory"); - return -ENOMEM; - } - - job->callback = callback; - job->user_data = user_data; - - g_mutex_lock(&worker->mutex); - g_queue_push_tail(worker->queue, job); - g_cond_signal(&worker->cond); - g_mutex_unlock(&worker->mutex); - - return 0; -} - -static int __set_comm(const char* name) { - int fd; - ssize_t bytes_written; - char path[PATH_MAX]; - pid_t tid = syscall(__NR_gettid); - - _I("[%s] TID(%d)", name, tid); - snprintf(path, sizeof(path), "/proc/%d/comm", tid); - fd = open(path, O_WRONLY); - if (fd < 0) { - _E("Failed to open %s. error(%d)", path, errno); - return -1; - } - - bytes_written = write(fd, name, strlen(name) + 1); - if (bytes_written < 0) { - _E("Failed to write name(%s)", name); - close(fd); - return -1; - } - - close(fd); - return 0; -} - -static gpointer __worker_thread_cb(gpointer data) { - struct worker_s* worker = (struct worker_s*)data; - struct job_s* job; - bool done = false; - - __set_comm(worker->name); - do { - g_mutex_lock(&worker->mutex); - if (g_queue_is_empty(worker->queue)) - g_cond_wait(&worker->cond, &worker->mutex); - - job = (struct job_s*)g_queue_pop_head(worker->queue); - g_mutex_unlock(&worker->mutex); - done = job->callback(job->user_data); - free(job); - } while (!done); - - return NULL; -} - -int _worker_create(const char* name, worker_h* worker) { - struct worker_s* handle; - - if (name == NULL || worker == NULL) { - _E("Invalid parameter"); - return -EINVAL; - } - - handle = static_cast(calloc(1, sizeof(worker_s))); - if (handle == NULL) { - _E("calloc() is failed"); - return -ENOMEM; - } - - g_mutex_init(&handle->mutex); - g_cond_init(&handle->cond); - - handle->name = strdup(name); - if (!handle->name) { - _E("strdup() is failed"); - _worker_destroy(handle); - return -ENOMEM; - } - - handle->queue = g_queue_new(); - if (!handle->queue) { - _E("g_queue_new() is failed"); - _worker_destroy(handle); - return -ENOMEM; - } - - handle->thread = g_thread_new(name, __worker_thread_cb, handle); - if (!handle->thread) { - _E("g_thread_new() is failed"); - _worker_destroy(handle); - return -ENOMEM; - } - - *worker = handle; - return 0; -} - -static bool __worker_done_cb(void* user_data) { - _W("Done"); - return true; -} - -void _worker_destroy(worker_h worker) { - if (worker == NULL) - return; - - if (worker->thread) { - _worker_add_job(worker, __worker_done_cb, NULL); - g_thread_join(worker->thread); - } - - if (worker->queue) - g_queue_free_full(worker->queue, (GDestroyNotify)free); - - if (worker->name) - free(worker->name); - - g_cond_clear(&worker->cond); - g_mutex_clear(&worker->mutex); - free(worker); -} diff --git a/src/launchpad-process-pool/launchpad_worker.h b/src/launchpad-process-pool/launchpad_worker.h deleted file mode 100644 index 0276545..0000000 --- a/src/launchpad-process-pool/launchpad_worker.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __LAUNCHPAD_WORKER_H__ -#define __LAUNCHPAD_WORKER_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct worker_s *worker_h; - -typedef bool (*worker_job_cb)(void *user_data); - -int _worker_add_job(worker_h worker, worker_job_cb callback, void *user_data); - -int _worker_create(const char *name, worker_h *worker); - -void _worker_destroy(worker_h worker); - -#ifdef __cplusplus -} -#endif - -#endif /* __LAUNCHPAD_WORKER_H__ */ diff --git a/src/launchpad-process-pool/worker.cc b/src/launchpad-process-pool/worker.cc new file mode 100644 index 0000000..28e3596 --- /dev/null +++ b/src/launchpad-process-pool/worker.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "launchpad-process-pool/worker.hh" + +#include +#include + +#include + +#include + +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { +namespace { + +const pid_t current_pid = getpid(); + +class Ender : public Worker::Job { + public: + bool IsDone() override { return true; } +}; + +} // namespace + +Worker::Worker(std::string name) : name_(std::move(name)) { + thread_ = std::thread([&]() -> void { RunThread(); }); +} + +Worker::~Worker() { + if (getpid() == current_pid) { + Add(std::make_shared()); + thread_.join(); + } +} + +void Worker::Add(std::shared_ptrjob) { + queue_.Push(std::move(job)); +} + +void Worker::SetComm() { + const std::string path = "/proc/" + std::to_string(gettid()) + "/comm"; + std::ofstream comm_file; + comm_file.open(path); + if (!comm_file.is_open()) { + _E("Failed to open %s", path.c_str()); + return; + } + + comm_file << name_; + comm_file.close(); +} + +void Worker::RunThread() { + _W("BEGIN"); + SetComm(); + while (true) { + auto job = queue_.WaitAndPop(); + job->Do(); + if (job->IsDone()) + break; + } + _W("END"); +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/worker.hh b/src/launchpad-process-pool/worker.hh new file mode 100644 index 0000000..ed12083 --- /dev/null +++ b/src/launchpad-process-pool/worker.hh @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LAUNCHPAD_PROCESS_POOL_WORKER_HH_ +#define LAUNCHPAD_PROCESS_POOL_WORKER_HH_ + +#include +#include +#include +#include + +#include + +namespace launchpad { + +class Worker { + public: + class Job { + public: + virtual ~Job() = default; + virtual void Do() {} + virtual bool IsDone() { return false; } + }; + + explicit Worker(std::string name); + virtual ~Worker(); + + void Add(std::shared_ptr job); + + private: + void SetComm(); + void RunThread(); + + private: + std::string name_; + std::thread thread_; + tizen_base::SharedQueue> queue_; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_WORKER_HH_ -- 2.7.4