From 3b4ad7fc8300e1e47562eabb033ec4d4ffdbb818 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 14 Mar 2023 05:21:53 +0000 Subject: [PATCH 01/16] Fix static analysis issues Types: - Uninitialized pointer read Change-Id: Ibb40848fcd278ff28216b7c2a41091a95e4d3b8c Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 83 +++++++++++++++++---------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 3699acb..9917e05 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -93,47 +93,47 @@ enum candidate_process_state_e { }; typedef struct { - int type; - bool prepared; - int pid; /* for hydra this pid is not the pid of hydra itself */ + int type = -1; + bool prepared = false; + int pid = CANDIDATE_NONE; /* for hydra this pid is not the pid of hydra itself */ /* but pid of non-hydra candidate, which was forked from hydra */ - int hydra_pid; - int loader_id; - int caller_pid; - int send_fd; - int hydra_fd; - int last_exec_time; - guint timer; - char* loader_name; - char* loader_path; - char* loader_extra; - int detection_method; - int timeout_val; - unsigned long long cpu_total_time; - unsigned long long cpu_idle_time; - int threshold; - int threshold_max; - int threshold_min; - int cur_event; - bool on_boot; - bool app_exists; - bool touched; - int activation_method; - int deactivation_method; - unsigned int ttl; - guint live_timer; - int state; - bool is_hydra; - bool app_check; - io_channel_h client_channel; - io_channel_h channel; - io_channel_h hydra_channel; - unsigned int score; - unsigned int pss; - int cpu_check_count; - int on_boot_timeout; - guint on_boot_timer; - int sched_priority; + int hydra_pid = CANDIDATE_NONE; + int loader_id = -1; + int caller_pid = CANDIDATE_NONE; + int send_fd = -1; + int hydra_fd = -1; + int last_exec_time = 0; + guint timer = 0; + char* loader_name = nullptr; + char* loader_path = nullptr; + char* loader_extra = nullptr; + int detection_method = 0; + int timeout_val = 0; + unsigned long long cpu_total_time = 0; + unsigned long long cpu_idle_time = 0; + int threshold = 0; + int threshold_max = 0; + int threshold_min = 0; + int cur_event = 0; + bool on_boot = false; + bool app_exists = false; + bool touched = false; + int activation_method = 0; + int deactivation_method = 0; + unsigned int ttl = 0; + guint live_timer = 0; + int state = 0; + bool is_hydra = false; + bool app_check = false; + io_channel_h client_channel = nullptr; + io_channel_h channel = nullptr; + io_channel_h hydra_channel = nullptr; + unsigned int score = 0; + unsigned int pss = 0; + int cpu_check_count = 0; + int on_boot_timeout = 0; + guint on_boot_timer = 0; + int sched_priority = 0; std::vector condition_path_exists; } candidate_process_context_t; @@ -2599,7 +2599,8 @@ static bool __handle_launch_event(int fd, io_condition_e cond, void* data) { } } - if (request->cmd < 0 || request->cmd >= ARRAY_SIZE(__request_handlers) || + if (request->cmd < 0 || + static_cast(request->cmd) >= ARRAY_SIZE(__request_handlers) || __request_handlers[request->cmd] == nullptr) { _E("Unknown command: %d", request->cmd); __request_send_result(request, -EINVAL); -- 2.7.4 From f85766b27ea8970bc82308e0baec47ce374f7434 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 13 Mar 2023 23:29:31 +0000 Subject: [PATCH 02/16] 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 From 46667cb2cb55c94f24b803c36544d86c05a37490 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 14 Mar 2023 03:55:34 +0000 Subject: [PATCH 03/16] Remove cpplint warning messages - Use uint64_t instead of C type long - Use reinterpret_cast instead of C-style cast - Delete Redundant blank line Change-Id: I238d613bcc3e484687c99daa2bf62ed9318ffa92 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 305 +++++++++++++++----------------- 1 file changed, 139 insertions(+), 166 deletions(-) diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 92d24f6..0980599 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -110,8 +110,8 @@ typedef struct { char* loader_extra = nullptr; int detection_method = 0; int timeout_val = 0; - unsigned long long cpu_total_time = 0; - unsigned long long cpu_idle_time = 0; + uint64_t cpu_total_time = 0; + uint64_t cpu_idle_time = 0; int threshold = 0; int threshold_max = 0; int threshold_min = 0; @@ -258,8 +258,8 @@ static gboolean __logger_recovery_cb(gpointer data); static gboolean __handle_queuing_slots(gpointer data) { candidate_process_context_t* cpc; - unsigned long long total = 0; - unsigned long long idle = 0; + uint64_t total = 0; + uint64_t idle = 0; if (__sequencer.idle_checker > 0) return G_SOURCE_CONTINUE; @@ -269,12 +269,12 @@ static gboolean __handle_queuing_slots(gpointer data) { return G_SOURCE_REMOVE; } - cpc = (candidate_process_context_t*)g_queue_pop_head(__sequencer.queue); + cpc = reinterpret_cast( + g_queue_pop_head(__sequencer.queue)); if (!cpc) { _E("Critical error!"); __sequencer.timer = 0; return G_SOURCE_REMOVE; - ; } if (cpc->app_check && !cpc->app_exists) { @@ -406,7 +406,7 @@ static candidate_process_context_t* __find_slot_from_static_type(int type) { return nullptr; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (type == cpc->type) return cpc; @@ -421,7 +421,7 @@ static candidate_process_context_t* __find_slot_from_pid(int pid) { GList* iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (pid == cpc->pid) return cpc; @@ -436,7 +436,7 @@ static candidate_process_context_t* __find_hydra_slot_from_pid(int pid) { GList* iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (cpc->is_hydra && pid == cpc->hydra_pid) return cpc; @@ -452,7 +452,7 @@ static candidate_process_context_t* __find_slot_from_caller_pid( GList* iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (caller_pid == cpc->caller_pid) return cpc; @@ -467,7 +467,7 @@ static candidate_process_context_t* __find_slot_from_loader_id(int id) { GList* iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (id == cpc->loader_id) return cpc; @@ -483,7 +483,7 @@ static candidate_process_context_t* __find_slot_from_loader_name( GList* iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (strcmp(cpc->loader_name, loader_name) == 0) return cpc; @@ -514,7 +514,7 @@ static void __update_slots_pss(void) { iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); iter = g_list_next(iter); if (cpc->pid == CANDIDATE_NONE) @@ -525,8 +525,8 @@ static void __update_slots_pss(void) { } static gint __compare_slot(gconstpointer a, gconstpointer b) { - candidate_process_context_t* slot_a = (candidate_process_context_t*)a; - candidate_process_context_t* slot_b = (candidate_process_context_t*)b; + auto* slot_a = reinterpret_cast(a); + auto* slot_b = reinterpret_cast(b); if (slot_a->is_hydra && !slot_b->is_hydra) return -1; @@ -552,7 +552,7 @@ static candidate_process_context_t* __get_running_slot(bool is_hydra) { iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) return cpc; @@ -568,7 +568,7 @@ static void __pause_all_running_slots(bool is_hydra) { iter = g_list_last(candidate_slot_list); while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) { __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, true); if (!_memory_monitor_is_low_memory()) @@ -585,7 +585,7 @@ static void __resume_all_slots(void) { iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true); iter = g_list_next(iter); @@ -723,9 +723,7 @@ static int __listen_candidate_process(int type, int loader_id) { memset(&addr, 0x00, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%u/%s%d-%d", - SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME, type, - loader_id); - + SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME, type, loader_id); return __listen_addr(&addr); } @@ -737,8 +735,7 @@ static int __listen_hydra_process(int type, int loader_id) { memset(&addr, 0x00, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d", - SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, type, loader_id); - + SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, type, loader_id); return __listen_addr(&addr); } @@ -817,8 +814,8 @@ static int __exec_loader_process(void* arg) { if (execv(argv[LOADER_ARG_PATH], argv) < 0) { _send_message_to_logger(argv[LOADER_ARG_PATH], - "Failed to prepare candidate process. error(%d:%s)", - errno, strerror_r(errno, err_buf, sizeof(err_buf))); + "Failed to prepare candidate process. error(%d:%s)", + errno, strerror_r(errno, err_buf, sizeof(err_buf))); } else { _D("Succeeded to prepare candidate_process"); } @@ -827,9 +824,7 @@ static int __exec_loader_process(void* arg) { } static gboolean __handle_deactivate_event(gpointer user_data) { - candidate_process_context_t* cpc; - - cpc = (candidate_process_context_t*)user_data; + auto* cpc = reinterpret_cast(user_data); __update_slot_state(cpc, launchpad::LoaderMethod::Ttl, false); _D("Deactivate event: type(%d), loader_name(%s)", cpc->type, cpc->loader_name); @@ -841,7 +836,8 @@ static void __set_live_timer(candidate_process_context_t* cpc) { if (!cpc) return; - if (cpc->deactivation_method & static_cast(launchpad::LoaderMethod::Ttl)) { + if (cpc->deactivation_method & + static_cast(launchpad::LoaderMethod::Ttl)) { if (cpc->live_timer == 0) { cpc->live_timer = g_timeout_add_seconds(cpc->ttl, __handle_deactivate_event, cpc); @@ -850,12 +846,13 @@ static void __set_live_timer(candidate_process_context_t* cpc) { } static int __hydra_send_request(int fd, enum hydra_cmd cmd) { - int sent = 0; - int size = (int)sizeof(cmd); - int send_ret = 0; + size_t sent = 0; + size_t size = sizeof(cmd); + ssize_t send_ret = 0; while (sent != size) { - send_ret = send(fd, (char*)&cmd + sent, size - sent, MSG_NOSIGNAL); + send_ret = send(fd, reinterpret_cast(&cmd) + sent, size - sent, + MSG_NOSIGNAL); if (send_ret == -1) { _E("send error! (%d)", errno); return -1; @@ -890,13 +887,9 @@ static void __candidate_info_free(candidate_info_t* info) { } static int __candidate_info_create(candidate_process_context_t* cpt, - candidate_info_t** candidate_info) { - char type_str[12] = { - 0, - }; - char loader_id_str[12] = { - 0, - }; + candidate_info_t** candidate_info) { + char type_str[12] = { 0, }; + char loader_id_str[12] = { 0, }; char argbuf[LOADER_ARG_LEN]; candidate_info_t* info; @@ -960,8 +953,8 @@ static int __prepare_candidate_process(int type, int loader_id) { return -1; } - _W("Candidate process. type: %d, loader_id: %d, pid: %d", info->type, - info->loader_id, info->pid); + _W("Candidate process. type: %d, loader_id: %d, pid: %d", + info->type, info->loader_id, info->pid); cpt = __find_slot(info->type, info->loader_id); if (cpt == nullptr) { _E("Not found slot."); @@ -985,9 +978,7 @@ static int __prepare_candidate_process(int type, int loader_id) { } static gboolean __handle_timeout_event(gpointer user_data) { - candidate_process_context_t* cpc; - - cpc = (candidate_process_context_t*)user_data; + auto* cpc = reinterpret_cast(user_data); cpc->timer = 0; _W("type(%d), loader_name(%s), state(%d)", @@ -1077,9 +1068,7 @@ static void __dispose_hydra_process(candidate_process_context_t* cpc) { } static int __send_launchpad_loader(candidate_process_context_t* cpc, - app_pkt_t* pkt, - const char* app_path, - int clifd) { + app_pkt_t* pkt, const char* app_path, int clifd) { int pid = -1; int ret; @@ -1088,8 +1077,7 @@ static int __send_launchpad_loader(candidate_process_context_t* cpc, return -1; __candidate_process_real_launch(cpc->send_fd, pkt); - _W("Request to candidate process, pid: %d, bin path: %s", cpc->pid, - app_path); + _W("Request to candidate process, pid: %d, bin path: %s", cpc->pid, app_path); pid = cpc->pid; cpc->pid = CANDIDATE_NONE; @@ -1116,17 +1104,16 @@ static int __normal_fork_exec(int argc, char** argv, const char* app_path) { if (execv(argv[LOADER_ARG_PATH], argv) < 0) { /* Flawfinder: ignore */ _send_message_to_logger(argv[LOADER_ARG_PATH], - "Failed to execute a file. error(%d:%s)", errno, - strerror_r(errno, err_buf, sizeof(err_buf))); + "Failed to execute a file. error(%d:%s)", + errno, strerror_r(errno, err_buf, sizeof(err_buf))); return -1; } /* never reach*/ return 0; } -static int __create_launcher_argv(int* argc, - char*** argv, - const char* app_type) { +static int __create_launcher_argv(int* argc, char*** argv, + const char* app_type) { int launcher_argc; char** launcher_argv; launchpad::LauncherInfoPtr launcher_info; @@ -1181,26 +1168,15 @@ static void __destroy_launcher_argv(int argc, char** argv) { free(argv); } -static int __create_app_argv(int* argc, - char*** argv, - const char* app_path, - bundle* kb, - const char* app_type) { +static int __create_app_argv(int* argc, char*** argv, const char* app_path, + bundle* kb, const char* app_type) { int new_argc; char** new_argv; bool attach = false; - struct app_arg debug_arg = { - 0, - }; - struct app_arg launcher_arg = { - 0, - }; - struct app_arg arg = { - 0, - }; - struct app_arg debug_extra_arg = { - 0, - }; + struct app_arg debug_arg = { 0, }; + struct app_arg launcher_arg = { 0, }; + struct app_arg arg = { 0, }; + struct app_arg debug_extra_arg = { 0, }; int ret; int i; int c; @@ -1251,7 +1227,7 @@ static int __create_app_argv(int* argc, return 0; } - new_argv = (char**)calloc(new_argc + 1, sizeof(char*)); + new_argv = reinterpret_cast(calloc(new_argc + 1, sizeof(char*))); if (new_argv == nullptr) { _E("out of memory"); free(arg.argv[LOADER_ARG_PATH]); @@ -1262,7 +1238,7 @@ static int __create_app_argv(int* argc, return -1; } - c = LOADER_ARG_PATH; + c = static_cast(LOADER_ARG_PATH); for (i = 0; i < debug_arg.argc; i++) new_argv[c++] = debug_arg.argv[i]; for (i = 0; i < launcher_arg.argc; i++) @@ -1278,9 +1254,8 @@ static int __create_app_argv(int* argc, return 0; } -static void __real_launch(const char* app_path, - bundle* kb, - appinfo_t* menu_info) { +static void __real_launch(const char* app_path, bundle* kb, + appinfo_t* menu_info) { int app_argc = 0; char** app_argv; int i; @@ -1303,10 +1278,8 @@ static void __real_launch(const char* app_path, __normal_fork_exec(app_argc, app_argv, app_path); } -static int __prepare_exec(const char* appid, - const char* app_path, - appinfo_t* menu_info, - bundle* kb) { +static int __prepare_exec(const char* appid, const char* app_path, + appinfo_t* menu_info, bundle* kb) { char* file_name; const char* enabled_light_user; char process_name[AUL_PR_NAME]; @@ -1324,7 +1297,7 @@ static int __prepare_exec(const char* appid, } ret = _enable_external_pkg(kb, menu_info->pkgid, - menu_info->global ? GLOBAL_USER : getuid()); + menu_info->global ? GLOBAL_USER : getuid()); if (ret < 0) return PAD_ERR_FAILED; @@ -1418,7 +1391,7 @@ static int __exec_app_process(void* arg) { PERF("prepare exec - first done"); ret = __prepare_exec(launch_arg->appid, launch_arg->app_path, - launch_arg->menu_info, launch_arg->kb); + launch_arg->menu_info, launch_arg->kb); if (ret < 0) return ret; @@ -1428,12 +1401,8 @@ static int __exec_app_process(void* arg) { return PAD_ERR_FAILED; } -static int __launch_directly(const char* appid, - const char* app_path, - int clifd, - bundle* kb, - appinfo_t* menu_info, - candidate_process_context_t* cpc) { +static int __launch_directly(const char* appid, const char* app_path, int clifd, + bundle* kb, appinfo_t* menu_info, candidate_process_context_t* cpc) { struct app_launch_arg arg; int pid; @@ -1459,8 +1428,8 @@ static int __create_sock_activation(void) { fds = sd_listen_fds(0); snprintf(launchpad_process_pool_sock_path, - sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s", - SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK); + sizeof(launchpad_process_pool_sock_path), "%s/daemons/%u/%s", + SOCKET_PATH, getuid(), PROCESS_POOL_LAUNCHPAD_SOCK); for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + fds; ++i) { if (sd_is_socket_unix(i, SOCK_STREAM, 1, launchpad_process_pool_sock_path, @@ -1506,11 +1475,9 @@ static int __launchpad_pre_init(int argc, char** argv) { return fd; } -static bool __handle_loader_client_event(int fd, - io_condition_e cond, - void* data) { +static bool __handle_loader_client_event(int fd, io_condition_e cond, + void* data) { auto* cpc = static_cast(data); - if (cpc == nullptr) return false; @@ -1528,9 +1495,8 @@ static bool __handle_loader_client_event(int fd, return true; } -static bool __handle_hydra_client_event(int fd, - io_condition_e cond, - void* data) { +static bool __handle_hydra_client_event(int fd, io_condition_e cond, + void* data) { auto* cpc = static_cast(data); int recv_pid = -1; int ret; @@ -1573,7 +1539,7 @@ static bool __handle_loader_event(int fd, io_condition_e cond, void* data) { if (!cpc->prepared) { ret = __accept_candidate_process(fd, &client_fd, &client_pid, - cpc->is_hydra ? -1 : cpc->pid); + cpc->is_hydra ? -1 : cpc->pid); if (ret >= 0) { /* for hydra need to set pid to pid of non-hydra candidate, */ /* which is connecting now */ @@ -1665,7 +1631,8 @@ static void __handle_sigchild(int pid, void* user_data) { cpc = __find_slot_from_caller_pid(pid); while (cpc) { - __remove_slot(static_cast(launchpad::LoaderType::Dynamic), cpc->loader_id); + __remove_slot(static_cast(launchpad::LoaderType::Dynamic), + cpc->loader_id); cpc = __find_slot_from_caller_pid(pid); } } @@ -1685,7 +1652,7 @@ static bool __handle_label_monitor(int fd, io_condition_e cond, void* data) { security_manager_app_labels_monitor_process(label_monitor); while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (cpc->is_hydra) { if (cpc->hydra_pid > 0) { __dispose_hydra_process(cpc); @@ -1729,15 +1696,15 @@ static void __update_threshold(candidate_process_context_t* cpc, float delta) { if (pos > 1.0f) pos = 1.0f; - cpc->threshold = - (int)(__interpolator(pos, cpc->threshold_max, cpc->threshold_min) * 100); - _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d", cpc->type, - delta, pos, cpc->threshold); + cpc->threshold = static_cast( + __interpolator(pos, cpc->threshold_max, cpc->threshold_min) * 100); + _D("[CPU] type:%d / delta:%f / input cursor : %f / threshold : %d", + cpc->type, delta, pos, cpc->threshold); } static gboolean __handle_idle_checker(gpointer data) { - unsigned long long total = 0; - unsigned long long idle = 0; + uint64_t total = 0; + uint64_t idle = 0; int per; candidate_process_context_t* cpc; @@ -1748,10 +1715,10 @@ static gboolean __handle_idle_checker(gpointer data) { return G_SOURCE_REMOVE; } - cpc = (candidate_process_context_t*)data; + cpc = reinterpret_cast(data); if (cpc->app_check && !cpc->app_exists) { - _W("The application is not installed. loader(%s:%d)", cpc->loader_name, - cpc->type); + _W("The application is not installed. loader(%s:%d)", + cpc->loader_name, cpc->type); __sequencer.idle_checker = 0; __sequencer.running_cpc = nullptr; return G_SOURCE_REMOVE; @@ -1765,8 +1732,8 @@ static gboolean __handle_idle_checker(gpointer data) { } if (cpc->pid != CANDIDATE_NONE) { - _W("Slot is already running. %d:%s:%d", cpc->type, cpc->loader_name, - cpc->pid); + _W("Slot is already running. %d:%s:%d", + cpc->type, cpc->loader_name, cpc->pid); __sequencer.idle_checker = 0; __sequencer.running_cpc = nullptr; return G_SOURCE_REMOVE; @@ -1795,7 +1762,7 @@ static gboolean __handle_idle_checker(gpointer data) { cpc->cpu_check_count++; if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) { _W("CPU check count has exceeded %d times. loader(%s:%d)", - cpc->cpu_check_count, cpc->loader_name, cpc->type); + cpc->cpu_check_count, cpc->loader_name, cpc->type); __sequencer.idle_checker = 0; __sequencer.running_cpc = nullptr; __sequencer_add_slot(cpc); @@ -1811,8 +1778,8 @@ static gboolean __on_boot_timeout_cb(gpointer user_data) { _W("type(%d), loader_name(%s)", context->type, context->loader_name); context->on_boot_timer = 0; if (context->pid != CANDIDATE_NONE) { - _E("Candidate process is already running. %d:%s:%d", context->type, - context->loader_name, context->pid); + _E("Candidate process is already running. %d:%s:%d", + context->type, context->loader_name, context->pid); } else { auto iter = context->condition_path_exists.begin(); while (iter != context->condition_path_exists.end()) { @@ -1847,7 +1814,7 @@ static int __add_idle_checker(int detection_method, GList* cur) { GList* iter = cur; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (!cpc->touched && cpc->on_boot && cpc->on_boot_timeout > 0) __add_on_boot_timer(cpc); @@ -1915,7 +1882,7 @@ static int __dispatch_cmd_add_loader(bundle* kb) { lid = __make_loader_id(); size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid); - loader_name = (char*)malloc(size + 1); + loader_name = reinterpret_cast(malloc(size + 1)); if (loader_name == nullptr) { _E("Out of memory"); return -1; @@ -1933,7 +1900,7 @@ static int __dispatch_cmd_add_loader(bundle* kb) { launchpad::LoaderMethod::Timeout | launchpad::LoaderMethod::Visibility); slot_info.activation_method = static_cast(launchpad::LoaderMethod::Request | - launchpad::LoaderMethod::AvailableMemory); + launchpad::LoaderMethod::AvailableMemory); slot_info.deactivation_method = static_cast( launchpad::LoaderMethod::Ttl | launchpad::LoaderMethod::OutOfMemory); slot_info.ttl = 600; @@ -1988,9 +1955,15 @@ static int __dispatch_cmd_add_app_defined_loader(bundle* kb) { slot_info.loader_name = loader_name; slot_info.loader_path = "/usr/bin/app-defined-loader"; slot_info.loader_extra = (const char*)extra; - slot_info.detection_method = static_cast(launchpad::LoaderMethod::Timeout) | static_cast(launchpad::LoaderMethod::Visibility); - slot_info.activation_method = static_cast(launchpad::LoaderMethod::Request) | static_cast(launchpad::LoaderMethod::AvailableMemory); - slot_info.deactivation_method = static_cast(launchpad::LoaderMethod::Ttl) | static_cast(launchpad::LoaderMethod::OutOfMemory); + slot_info.detection_method = + static_cast(launchpad::LoaderMethod::Timeout) | + static_cast(launchpad::LoaderMethod::Visibility); + slot_info.activation_method = + static_cast(launchpad::LoaderMethod::Request) | + static_cast(launchpad::LoaderMethod::AvailableMemory); + slot_info.deactivation_method = + static_cast(launchpad::LoaderMethod::Ttl) | + static_cast(launchpad::LoaderMethod::OutOfMemory); slot_info.ttl = info->GetTtl(); slot_info.timeout_val = 2000; slot_info.threshold_max = launchpad::DefaultCpuThresholdMax; @@ -2012,8 +1985,10 @@ static int __dispatch_cmd_add_app_defined_loader(bundle* kb) { lid = cpc->loader_id; } - if (cpc->pid == CANDIDATE_NONE) - __prepare_candidate_process(static_cast(launchpad::LoaderType::Dynamic), lid); + if (cpc->pid == CANDIDATE_NONE) { + __prepare_candidate_process( + static_cast(launchpad::LoaderType::Dynamic), lid); + } return lid; } @@ -2025,7 +2000,8 @@ static int __dispatch_cmd_remove_loader(bundle* kb) { _W("cmd remove loader"); if (id) { lid = atoi(id); - if (__remove_slot(static_cast(launchpad::LoaderType::Dynamic), lid) == 0) + if (__remove_slot( + static_cast(launchpad::LoaderType::Dynamic), lid) == 0) return 0; } @@ -2420,8 +2396,8 @@ static int __launch_request_prepare(request_h request) { request->loader_id = PAD_LOADER_ID_DIRECT; } } else if (menu_info->comp_type && menu_info->app_type && - !strcmp(menu_info->comp_type, "widgetapp") && - !strcmp(menu_info->app_type, "webapp")) { + !strcmp(menu_info->comp_type, "widgetapp") && + !strcmp(menu_info->app_type, "webapp")) { request->loader_id = PAD_LOADER_ID_DIRECT; } else { request->loader_id = __get_loader_id(request->kb); @@ -2438,7 +2414,7 @@ static int __launch_request_prepare(request_h request) { } _modify_bundle(request->kb, request->caller_pid, request->menu_info, - request->cmd); + request->cmd); if (menu_info->appid == nullptr) { _E("Unable to get appid from app info"); return -1; @@ -2472,7 +2448,8 @@ static void __handle_direct_launch(request_h request) { request->org_cpc->timer = 0; } - __update_slot_state(request->org_cpc, launchpad::LoaderMethod::Request, true); + __update_slot_state(request->org_cpc, launchpad::LoaderMethod::Request, + true); __set_timer(request->org_cpc); } } @@ -2483,11 +2460,10 @@ static void __fork_processing(request_h request) { _W("appid: %s", request->menu_info->appid); request->pid = __launch_directly(request->menu_info->appid, request->app_path, - request->clifd, request->kb, - request->menu_info, nullptr); + request->clifd, request->kb, request->menu_info, nullptr); if (request->pid == -1) { _E("Failed to create a child process. appid(%s)", - request->menu_info->appid); + request->menu_info->appid); } __request_send_result(request, request->pid); @@ -2502,10 +2478,10 @@ static int __launch_request_do(request_h request) { return 0; } - _W("Launch %d type process. appid(%s)", request->cpc->type, - request->menu_info->appid); + _W("Launch %d type process. appid(%s)", + request->cpc->type, request->menu_info->appid); request->pid = __send_launchpad_loader(request->cpc, request->pkt, - request->app_path, request->clifd); + request->app_path, request->clifd); return 0; } @@ -2529,8 +2505,8 @@ static int __launch_request_handler(request_h request) { __launch_request_complete(request); traceEnd(TTRACE_TAG_APPLICATION_MANAGER); - _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", request->menu_info->appid, - request->pid); + _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", + request->menu_info->appid, request->pid); return 0; } @@ -2666,13 +2642,15 @@ static candidate_process_context_t* __create_slot(slot_info_t* info) { cpc->sched_priority = info->sched_priority; cpc->condition_path_exists = info->condition_path_exists; - if ((cpc->deactivation_method & static_cast(launchpad::LoaderMethod::OutOfMemory)) && __is_low_memory()) + if ((cpc->deactivation_method & + static_cast(launchpad::LoaderMethod::OutOfMemory)) && + __is_low_memory()) cpc->state = CANDIDATE_PROCESS_STATE_PAUSED; else cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; - _W("loader(%s), type(%d), state(%d)", cpc->loader_name, cpc->type, - cpc->state); + _W("loader(%s), type(%d), state(%d)", + cpc->loader_name, cpc->type, cpc->state); return cpc; } @@ -2695,9 +2673,8 @@ static candidate_process_context_t* __add_slot(slot_info_t* info) { fd = __listen_candidate_process(cpc->type, cpc->loader_id); if (fd == -1) { - _E("[launchpad] Listening the socket to " - "the type %d candidate process failed.", - cpc->type); + _E("Listening the socket to the type %d candidate process failed.", + cpc->type); __destroy_slot(cpc); return nullptr; } @@ -2714,9 +2691,8 @@ static candidate_process_context_t* __add_slot(slot_info_t* info) { if (info->is_hydra) { hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id); if (hydra_fd == -1) { - _E("[launchpad] Listening the socket to " - "the type %d hydra process failed.", - cpc->type); + _E("Listening the socket to the type %d hydra process failed.", + cpc->type); __destroy_slot(cpc); return nullptr; } @@ -2743,7 +2719,7 @@ static int __remove_slot(int type, int loader_id) { iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); if (type == cpc->type && loader_id == cpc->loader_id) { __dispose_candidate_process(cpc); candidate_slot_list = g_list_delete_link(candidate_slot_list, iter); @@ -2777,9 +2753,8 @@ static int __init_launchpad_fd(int argc, char** argv) { return 0; } -static bool __on_directory_create(const char* event_name, - uint32_t mask, - void* user_data) { +static bool __on_directory_create(const char* event_name, uint32_t mask, + void* user_data) { if (!event_name) { _E("Invalid parameter"); return true; @@ -2795,8 +2770,7 @@ static bool __on_directory_create(const char* event_name, } static bool __on_file_change(const char* event_name, - uint32_t mask, - void* user_data) { + uint32_t mask, void* user_data) { char buf[PATH_MAX]; char* ext; launchpad::LoaderInfoPtr info; @@ -2833,7 +2807,7 @@ static void __init_app_defined_loader_monitor(void) { if (ret < 0) { _W("Failed to access %s", APP_DEFINED_LOADER_INFO_PATH); ret = _inotify_add_watch(OPT_SHARE_PATH, IN_CREATE, __on_directory_create, - nullptr); + nullptr); if (ret != 0) _E("Failed to add inotify watch %s", OPT_SHARE_PATH); @@ -2841,7 +2815,7 @@ static void __init_app_defined_loader_monitor(void) { } ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH, IN_CREATE | IN_DELETE, - __on_file_change, nullptr); + __on_file_change, nullptr); if (ret < 0) { _E("Failed to add inotify watch %s", APP_DEFINED_LOADER_INFO_PATH); @@ -2886,8 +2860,6 @@ static int __init_label_monitor_fd(void) { return err_handler(); return 0; - - } static int __verify_loader_caps(const char* loader) { @@ -2994,7 +2966,8 @@ static void __add_slot_from_info(const launchpad::LoaderInfoPtr& info) { slot_info.loader_extra = (const char*)extra; slot_info.detection_method = static_cast(info->GetDetectionMethod()); slot_info.activation_method = static_cast(info->GetActivationMethod()); - slot_info.deactivation_method = static_cast(info->GetDeactivationMethod()); + slot_info.deactivation_method = static_cast( + info->GetDeactivationMethod()); slot_info.ttl = info->GetTtl(); slot_info.timeout_val = info->GetTimeoutVal(); slot_info.on_boot = info->IsOnBoot(); @@ -3008,10 +2981,10 @@ static void __add_slot_from_info(const launchpad::LoaderInfoPtr& info) { static_cast(launchpad::LoaderType::User) + user_slot_offset)); user_slot_offset++; __get_app_type_string(info, buf, sizeof(buf)); - _I("candidate slot. app-type(%s) loader-type(%d)", buf, - static_cast(info->GetType())); - _print_hwc_log("candidate slot. app-type(%s) loader-type(%d)", buf, - static_cast(info->GetType())); + _I("candidate slot. app-type(%s) loader-type(%d)", + buf, static_cast(info->GetType())); + _print_hwc_log("candidate slot. app-type(%s) loader-type(%d)", + buf, static_cast(info->GetType())); } } @@ -3085,7 +3058,7 @@ static void __memory_status_low_changed_cb(keynode_t* node, void* data) { _W("Low memory"); iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, false); iter = g_list_next(iter); } @@ -3101,7 +3074,7 @@ static void __memory_status_normal_changed_cb(keynode_t* node, void* data) { _W("Normal"); iter = candidate_slot_list; while (iter) { - cpc = (candidate_process_context_t*)iter->data; + cpc = reinterpret_cast(iter->data); __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true); iter = g_list_next(iter); } @@ -3123,7 +3096,7 @@ static void __unregister_vconf_events(void) { vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __region_format_changed_cb); vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang); vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, - __hw_acceleration_changed_cb); + __hw_acceleration_changed_cb); } static int __register_vconf_events(void) { @@ -3138,7 +3111,7 @@ static int __register_vconf_events(void) { _E("Failed to get vconf hw acceleration. err = %d", r); r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, - __hw_acceleration_changed_cb, nullptr); + __hw_acceleration_changed_cb, nullptr); if (r != VCONF_OK) { _E("Failed to register callback for hw acceleration. err = %d", r); } @@ -3160,7 +3133,7 @@ static int __register_vconf_events(void) { } r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, - __region_format_changed_cb, nullptr); + __region_format_changed_cb, nullptr); if (r != VCONF_OK) _E("Failed to register callback for regionformat. err = %d", r); @@ -3244,7 +3217,7 @@ static int __init_logger_fd(void) { auto cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; __logger_channel = _io_channel_create(fd, static_cast(cond), - __handle_logger, nullptr); + __handle_logger, nullptr); if (!__logger_channel) { close(fd); return -1; -- 2.7.4 From 6bba9ec53d65736a208c2322753a001d80a4e831 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Sun, 19 Mar 2023 23:58:27 +0000 Subject: [PATCH 04/16] Refactor Memory Monitor The launchpad memory monitor is implemented using C++ language. Change-Id: I13a530d912a43ecff1271e78ede22334da9344c3 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 82 +++++++----- .../launchpad_memory_monitor.cc | 142 --------------------- src/launchpad-process-pool/memory_monitor.cc | 95 ++++++++++++++ src/launchpad-process-pool/memory_monitor.hh | 57 +++++++++ src/lib/launchpad-common/procfs.cc | 113 ++++++++++++++++ .../launchpad-common/procfs.hh} | 28 ++-- 6 files changed, 334 insertions(+), 183 deletions(-) delete mode 100644 src/launchpad-process-pool/launchpad_memory_monitor.cc create mode 100644 src/launchpad-process-pool/memory_monitor.cc create mode 100644 src/launchpad-process-pool/memory_monitor.hh create mode 100644 src/lib/launchpad-common/procfs.cc rename src/{launchpad-process-pool/launchpad_memory_monitor.h => lib/launchpad-common/procfs.hh} (51%) diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 0980599..cb240cc 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -41,25 +41,26 @@ #include #include +#include + #include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/launcher_info.hh" #include "launchpad-process-pool/launchpad_config.h" #include "launchpad-process-pool/launchpad_debug.h" #include "launchpad-process-pool/launchpad_inotify.h" #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/loader_info.hh" #include "launchpad-process-pool/slot_info.h" #include "lib/common/inc/key.h" #include "lib/common/inc/launchpad_common.h" #include "lib/common/inc/launchpad_plugin.h" -#include "lib/common/inc/launchpad_proc.h" #include "lib/common/inc/launchpad_types.h" #include "lib/common/inc/perf.h" #include "launchpad-process-pool/dbus.hh" #include "launchpad-process-pool/log.hh" +#include "launchpad-process-pool/memory_monitor.hh" #include "launchpad-process-pool/worker.hh" #define AUL_PR_NAME 16 @@ -130,7 +131,7 @@ typedef struct { io_channel_h channel = nullptr; io_channel_h hydra_channel = nullptr; unsigned int score = 0; - unsigned int pss = 0; + uint64_t pss = 0; int cpu_check_count = 0; int on_boot_timeout = 0; guint on_boot_timer = 0; @@ -200,6 +201,8 @@ typedef request_t* request_h; typedef int (*request_handler)(request_h request); +static void HandleMemoryStatusChangedEvent(bool low_memory); + namespace { class CleanupInfo : public launchpad::Worker::Job { @@ -218,6 +221,36 @@ class CleanupInfo : public launchpad::Worker::Job { pid_t pid_; }; +class MemoryManager : public launchpad::MemoryMonitor, + public launchpad::MemoryMonitor::IEvent { + public: + MemoryManager(const MemoryManager&) = delete; + MemoryManager& operator = (const MemoryManager&) = delete; + MemoryManager(MemoryManager&&) = delete; + MemoryManager& operator = (MemoryManager&&) = delete; + + static MemoryManager& GetInst() { + static MemoryManager inst; + return inst; + } + + void Init() { + Start(); + } + + void Finish() { + Stop(); + } + + private: + MemoryManager() : MemoryMonitor(this) {} + ~MemoryManager() {} + + void OnMemoryStatusChanged(bool low_memory) override { + HandleMemoryStatusChangedEvent(low_memory); + } +}; + int __sys_hwacc; std::unique_ptr loader_info_manager; std::unique_ptr app_defined_loader_info_manager; @@ -520,7 +553,7 @@ static void __update_slots_pss(void) { if (cpc->pid == CANDIDATE_NONE) continue; - _proc_get_mem_pss(cpc->pid, &cpc->pss); + launchpad::Procfs::GetPssMemory(cpc->pid, &cpc->pss); } } @@ -571,7 +604,7 @@ static void __pause_all_running_slots(bool is_hydra) { cpc = reinterpret_cast(iter->data); if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) { __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, true); - if (!_memory_monitor_is_low_memory()) + if (!MemoryManager::GetInst().IsLowMemory()) return; } @@ -972,7 +1005,7 @@ static int __prepare_candidate_process(int type, int loader_id) { launchpad::Log::Print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)", info->pid, cpt->loader_id, cpt->loader_name); - _memory_monitor_reset_timer(); + MemoryManager::GetInst().Reset(); __candidate_info_free(info); return 0; } @@ -2009,17 +2042,13 @@ static int __dispatch_cmd_remove_loader(bundle* kb) { } static int __check_caller_by_pid(int pid) { - int ret; - char buf[PATH_MAX] = { - 0, - }; - - ret = _proc_get_attr(pid, buf, sizeof(buf)); - if (ret < 0) + std::string attr = launchpad::Procfs::GetAttrCurrent(pid); + if (attr.empty()) return -1; - if (strcmp(buf, "User") == 0 || strcmp(buf, "System") == 0 || - strcmp(buf, "System::Privileged") == 0) + if (attr.compare("User") == 0 || + attr.compare("System") == 0 || + attr.compare("System::Privileged") == 0) return 0; return -1; @@ -2425,7 +2454,7 @@ static int __launch_request_prepare(request_h request) { } static void __launch_request_complete(request_h request) { - _memory_monitor_reset_timer(); + MemoryManager::GetInst().Reset(); __request_send_result(request, request->pid); if (request->pid > 0) { @@ -3011,7 +3040,7 @@ static void __add_app_defined_loaders(void) { } static bool __is_low_memory(void) { - if (_memory_monitor_is_low_memory()) + if (MemoryManager::GetInst().IsLowMemory()) return true; if (__memory_status_low >= MEMORY_STATUS_LOW) @@ -3226,14 +3255,12 @@ static int __init_logger_fd(void) { return 0; } -static int __memory_monitor_cb(bool low_memory, void* user_data) { - candidate_process_context_t* cpc; - - cpc = __get_running_slot(false); - if (!cpc && low_memory) - return -1; - +static void HandleMemoryStatusChangedEvent(bool low_memory) { if (low_memory) { + candidate_process_context_t* cpc = __get_running_slot(false); + if (cpc == nullptr) + return; + _W("Low memory"); __update_slots_pss(); @@ -3242,8 +3269,6 @@ static int __memory_monitor_cb(bool low_memory, void* user_data) { } else { __resume_all_slots(); } - - return 0; } static gboolean __logger_recovery_cb(gpointer data) { @@ -3332,8 +3357,7 @@ static int __before_loop(int argc, char** argv) { _W("Failed to initialize config"); _inotify_init(); - _memory_monitor_init(); - _memory_monitor_set_event_cb(__memory_monitor_cb, nullptr); + MemoryManager::GetInst().Init(); MAX_CPU_CHECK_COUNT = _config_get_int_value(CONFIG_TYPE_CPU_CHECKER_MAX_COUNT); @@ -3366,7 +3390,7 @@ static int __before_loop(int argc, char** argv) { static void __after_loop(void) { launchpad::Log::Finish(); cleaner.reset(); - _memory_monitor_fini(); + MemoryManager::GetInst().Finish(); __unregister_vconf_events(); if (__pid_table) g_hash_table_destroy(__pid_table); diff --git a/src/launchpad-process-pool/launchpad_memory_monitor.cc b/src/launchpad-process-pool/launchpad_memory_monitor.cc deleted file mode 100644 index c69fe73..0000000 --- a/src/launchpad-process-pool/launchpad_memory_monitor.cc +++ /dev/null @@ -1,142 +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_memory_monitor.h" - -#include -#include -#include -#include -#include - -#include "launchpad-process-pool/launchpad_config.h" -#include "lib/common/inc/launchpad_proc.h" -#include "lib/common/inc/log_private.h" - -#define INTERVAL_BASE_RATE 0.15f - -struct memory_monitor_s { - unsigned int threshold; - unsigned int prev_used_ratio; - unsigned int base_interval; - unsigned int interval; - bool low_memory; - guint tag; - memory_monitor_cb callback; - void* user_data; -}; - -static struct memory_monitor_s __monitor; - -static void __memory_monitor_start(void); - -static gboolean __memory_check_cb(gpointer data) { - bool low_memory; - - __monitor.tag = 0; - low_memory = _memory_monitor_is_low_memory(); - if (__monitor.low_memory != low_memory && __monitor.callback) - __monitor.callback(low_memory, __monitor.user_data); - - __monitor.low_memory = low_memory; - __memory_monitor_start(); - - return G_SOURCE_REMOVE; -} - -static void __memory_monitor_stop(void) { - if (!__monitor.tag) - return; - - g_source_remove(__monitor.tag); - __monitor.tag = 0; -} - -static void __memory_monitor_start(void) { - if (__monitor.threshold == 100) - return; - - if (__monitor.tag) - return; - - __monitor.tag = g_timeout_add(__monitor.interval, __memory_check_cb, NULL); - - __monitor.interval += __monitor.interval * INTERVAL_BASE_RATE; -} - -int _memory_monitor_reset_timer(void) { - _W("Reset"); - __monitor.interval = __monitor.base_interval; - - __memory_monitor_stop(); - __memory_monitor_start(); - - return 0; -} - -bool _memory_monitor_is_low_memory(void) { - unsigned int mem_used_ratio = 0; - - if (__monitor.threshold == 100) - return false; - - _proc_get_mem_used_ratio(&mem_used_ratio); - - _W("previous used ratio(%u), current used ratio(%u)", - __monitor.prev_used_ratio, mem_used_ratio); - - __monitor.prev_used_ratio = mem_used_ratio; - - if (mem_used_ratio > __monitor.threshold) - return true; - - return false; -} - -int _memory_monitor_set_event_cb(memory_monitor_cb callback, void* user_data) { - __monitor.callback = callback; - __monitor.user_data = user_data; - - return 0; -} - -int _memory_monitor_init(void) { - int ret; - - _W("MEMORY_MONITOR_INIT"); - - __monitor.threshold = - _config_get_int_value(CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD); - __monitor.base_interval = - _config_get_int_value(CONFIG_TYPE_MEMORY_MONITOR_INTERVAL); - __monitor.interval = __monitor.base_interval; - - ret = _proc_get_mem_used_ratio(&__monitor.prev_used_ratio); - if (ret != 0) { - _E("Failed to get mem used ratio. error(%d)", ret); - return ret; - } - - __memory_monitor_start(); - - return 0; -} - -void _memory_monitor_fini(void) { - _W("MEMORY_MONITOR_FINI"); - - __memory_monitor_stop(); -} diff --git a/src/launchpad-process-pool/memory_monitor.cc b/src/launchpad-process-pool/memory_monitor.cc new file mode 100644 index 0000000..54acde4 --- /dev/null +++ b/src/launchpad-process-pool/memory_monitor.cc @@ -0,0 +1,95 @@ +/* + * 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/memory_monitor.hh" + +#include + +#include "launchpad-process-pool/launchpad_config.h" +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const float INTERVAL_BASE_RATE = 0.15f; + +} // namespace + +MemoryMonitor::MemoryMonitor(IEvent* listener) : listener_(listener) { + threshold_ = _config_get_int_value(CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD); + base_interval_ = _config_get_int_value(CONFIG_TYPE_MEMORY_MONITOR_INTERVAL); + interval_ = base_interval_; +} + +MemoryMonitor::~MemoryMonitor() { + Stop(); +} + +bool MemoryMonitor::IsLowMemory() { + if (threshold_ == 100) + return false; + + uint32_t usage = 0; + Procfs::GetMemoryUsage(&usage); + _W("Previous used ratio: %u, current used ratio: %u", + previous_usage_, usage); + previous_usage_ = usage; + + if (usage > threshold_) + return true; + + return false; +} + +void MemoryMonitor::Reset() { + _W("Reset"); + interval_ = base_interval_; + + Stop(); + Start(); +} + +void MemoryMonitor::Start() { + if (threshold_ == 100) + return; + + if (timer_ != 0) + return; + + timer_ = g_timeout_add(interval_, TimeoutCb, this); + interval_ += interval_ * INTERVAL_BASE_RATE; +} + +void MemoryMonitor::Stop() { + if (timer_ != 0) { + g_source_remove(timer_); + timer_ = 0; + } +} + +gboolean MemoryMonitor::TimeoutCb(gpointer user_data) { + auto* handle = static_cast(user_data); + handle->timer_ = 0; + bool low_memory = handle->IsLowMemory(); + if (low_memory != handle->low_memory_ && handle->listener_) + handle->listener_->OnMemoryStatusChanged(low_memory); + + handle->low_memory_ = low_memory; + handle->Start(); + return G_SOURCE_REMOVE; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/memory_monitor.hh b/src/launchpad-process-pool/memory_monitor.hh new file mode 100644 index 0000000..34f9a2c --- /dev/null +++ b/src/launchpad-process-pool/memory_monitor.hh @@ -0,0 +1,57 @@ +/* + * 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_MEMORY_MONITOR_HH_ +#define LAUNCHPAD_PROCESS_POOL_MEMORY_MONITOR_HH_ + +#include + +#include + +namespace launchpad { + +class MemoryMonitor { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnMemoryStatusChanged(bool low_memory) = 0; + }; + + explicit MemoryMonitor(IEvent* listener); + virtual ~MemoryMonitor(); + + bool IsLowMemory(); + void Reset(); + void Stop(); + void Start(); + + private: + static gboolean TimeoutCb(gpointer user_data); + + private: + IEvent* listener_; + uint32_t threshold_ = 0; + uint32_t previous_usage_ = 0; + guint base_interval_ = 0; + guint interval_ = 0; + guint timer_ = 0; + bool low_memory_ = false; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_MEMORY_MONITOR_HH_ diff --git a/src/lib/launchpad-common/procfs.cc b/src/lib/launchpad-common/procfs.cc new file mode 100644 index 0000000..ac9596b --- /dev/null +++ b/src/lib/launchpad-common/procfs.cc @@ -0,0 +1,113 @@ +/* + * 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-common/procfs.hh" + +#include + +#include +#include +#include +#include +#include + +#include "launchpad-common/log_private.hh" + +namespace launchpad { + +void Procfs::GetMemoryUsage(uint32_t* usage) { + if (usage == nullptr) { + _E("Invalid argument"); + return; + } + + uint64_t mem_total = 0; + uint64_t mem_free = 0; + uint64_t mem_available = 0; + uint64_t mem_cached = 0; + + std::ifstream stream("/proc/meminfo"); + std::string line; + while (getline(stream, line)) { + std::istringstream iss(line); + std::string key; + uint64_t value; + + if (iss >> key >> value) { + if (key == "MemTotal:") + mem_total = value; + else if (key == "MemAvailable:") + mem_available = value; + else if (key == "MemFree:") + mem_free = value; + else if (key == "Cached:") + mem_cached = value; + } + } + + if (mem_total == 0) { + _E("Failed to get total memory size"); + return; + } + + if (mem_available == 0) + mem_available = mem_free + mem_cached; + + *usage = (mem_total - mem_available) * 100 / mem_total; + _W("usage: %u %%", *usage); +} + +void Procfs::GetPssMemory(pid_t pid, uint64_t* mem_pss) { + if (pid < 1 || mem_pss == nullptr) { + _E("Invalid parameter"); + return; + } + + std::ifstream file("/proc/" + std::to_string(pid) + "/smaps"); + std::string line; + uint64_t total_pss = 0; + + while (std::getline(file, line)) { + uint64_t pss = 0; + if (std::sscanf(line.c_str(), "Pss: %llu kB", &pss) == 1) + total_pss += pss; + } + + *mem_pss = total_pss; +} + +std::string Procfs::GetAttrCurrent(pid_t pid) { + const std::string path = "/proc/" + std::to_string(pid) + "/attr/current"; + std::ifstream file(path); + if (!file.is_open()) { + _E("%s is not opened", path.c_str()); + return {}; + } + + std::stringstream buffer; + buffer << file.rdbuf(); + file.close(); + + const std::string result = buffer.str(); + if (result.empty()) { + _E("file is empty"); + return {}; + } + + return result; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/launchpad_memory_monitor.h b/src/lib/launchpad-common/procfs.hh similarity index 51% rename from src/launchpad-process-pool/launchpad_memory_monitor.h rename to src/lib/launchpad-common/procfs.hh index a8486be..4c45e7a 100644 --- a/src/launchpad-process-pool/launchpad_memory_monitor.h +++ b/src/lib/launchpad-common/procfs.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * 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. @@ -14,21 +14,25 @@ * limitations under the License. */ -#ifndef __LAUNCHPAD_MEMORY_MONITOR_H__ -#define __LAUNCHPAD_MEMORY_MONITOR_H__ +#ifndef LIB_LAUNCHPAD_COMMON_PROCFS_HH_ +#define LIB_LAUNCHPAD_COMMON_PROCFS_HH_ -#include +#include -typedef int (*memory_monitor_cb)(bool low_memory, void *user_data); +#include -int _memory_monitor_init(void); +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) -void _memory_monitor_fini(void); +namespace launchpad { -int _memory_monitor_set_event_cb(memory_monitor_cb callback, void *user_data); +class EXPORT_API Procfs { + public: + static void GetMemoryUsage(uint32_t* usage); + static void GetPssMemory(pid_t pid, uint64_t* mem_pss); + static std::string GetAttrCurrent(pid_t pid); +}; -int _memory_monitor_reset_timer(void); +} // namespace launchpad -bool _memory_monitor_is_low_memory(void); - -#endif /* __LAUNCHPAD_MEMORY_MONITOR_H__ */ +#endif // LIB_LAUNCHPAD_COMMON_PROCFS_HH_ -- 2.7.4 From 4c9af3af61b50bb4eea8b75713ea116b188fa3a1 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 20 Mar 2023 07:24:43 +0000 Subject: [PATCH 05/16] Refactor launchpad signal The launchpad signal is implemented using C++ language. Change-Id: I633d2a5d58f01b4fdf70df9613fb1dbd1a2c88b2 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/hydra_sigchld_event.cc | 87 +++++ src/launchpad-process-pool/hydra_sigchld_event.hh | 53 +++ src/launchpad-process-pool/launchpad.cc | 28 +- src/launchpad-process-pool/launchpad_signal.cc | 448 ---------------------- src/launchpad-process-pool/launchpad_signal.h | 38 -- src/launchpad-process-pool/sigchld_event.cc | 66 ++++ src/launchpad-process-pool/sigchld_event.hh | 54 +++ src/launchpad-process-pool/signal_manager.cc | 198 ++++++++++ src/launchpad-process-pool/signal_manager.hh | 80 ++++ src/lib/launchpad-common/peer_credentials.cc | 54 +++ src/lib/launchpad-common/peer_credentials.hh | 48 +++ src/lib/launchpad-common/socket.cc | 103 +++++ src/lib/launchpad-common/socket.hh | 47 +++ 13 files changed, 805 insertions(+), 499 deletions(-) create mode 100644 src/launchpad-process-pool/hydra_sigchld_event.cc create mode 100644 src/launchpad-process-pool/hydra_sigchld_event.hh delete mode 100644 src/launchpad-process-pool/launchpad_signal.cc delete mode 100644 src/launchpad-process-pool/launchpad_signal.h create mode 100644 src/launchpad-process-pool/sigchld_event.cc create mode 100644 src/launchpad-process-pool/sigchld_event.hh create mode 100644 src/launchpad-process-pool/signal_manager.cc create mode 100644 src/launchpad-process-pool/signal_manager.hh create mode 100644 src/lib/launchpad-common/peer_credentials.cc create mode 100644 src/lib/launchpad-common/peer_credentials.hh create mode 100644 src/lib/launchpad-common/socket.cc create mode 100644 src/lib/launchpad-common/socket.hh diff --git a/src/launchpad-process-pool/hydra_sigchld_event.cc b/src/launchpad-process-pool/hydra_sigchld_event.cc new file mode 100644 index 0000000..6f26dd1 --- /dev/null +++ b/src/launchpad-process-pool/hydra_sigchld_event.cc @@ -0,0 +1,87 @@ +/* + * 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/hydra_sigchld_event.hh" + +#include + +#include +#include + +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const char HYDRA_SIGCHLD_SOCK[] = ".hydra-sigchld-sock"; +const int MAX_PENDING_CONNECTION = 128; +const int MAX_RECEIVE_BUFFER = 131071; + +int CheckPermission(pid_t pid) { + std::string attr = Procfs::GetAttrCurrent(pid); + if (attr.empty()) + return -1; + + if (attr.compare("User") == 0 || + attr.compare("System") == 0 || + attr.compare("System::Privileged") == 0) + return 0; + + _E("Permission denied. peer(%d:%s)", pid, attr.c_str()); + return -1; +} + +} // namespace + +HydraSigchldEvent::HydraSigchldEvent(IEvent* listener) + : listener_(listener), + socket_(new ServerSocket()) { + std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) + + HYDRA_SIGCHLD_SOCK; + socket_->Bind(endpoint); + socket_->Listen(MAX_PENDING_CONNECTION); + socket_->SetReceiveBufferSize(MAX_RECEIVE_BUFFER); + + channel_.reset(new IOChannel(socket_->GetFd(), IOChannel::IOCondition::IO_IN, + this)); + channel_->SetCloseOnDestroy(false); +} + +HydraSigchldEvent::~HydraSigchldEvent() { + if (getpid() != current_pid_) + socket_->RemoveFd(); +} + +void HydraSigchldEvent::OnIOEventReceived(int fd, int condition) { + auto client_socket = socket_->Accept(); + if (!client_socket) + return; + + auto peer_creds = PeerCredentials::Get(client_socket->GetFd()); + if (!peer_creds) { + if (CheckPermission(peer_creds->GetPid()) != 0) + return; + } + + pid_t pid = -1; + if (client_socket->Receive(&pid, sizeof(pid)) != 0) + return; + + if (listener_ != nullptr) + listener_->OnHydraSigchld(pid); +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/hydra_sigchld_event.hh b/src/launchpad-process-pool/hydra_sigchld_event.hh new file mode 100644 index 0000000..cc703cd --- /dev/null +++ b/src/launchpad-process-pool/hydra_sigchld_event.hh @@ -0,0 +1,53 @@ +/* + * 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_HYDRA_SIGCHLD_EVENT_HH_ +#define LAUNCHPAD_PROCESS_POOL_HYDRA_SIGCHLD_EVENT_HH_ + +#include +#include + +#include + +#include +#include + +namespace launchpad { + +class HydraSigchldEvent : public IOChannel::IEvent { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnHydraSigchld(pid_t pid) = 0; + }; + + explicit HydraSigchldEvent(IEvent* listener); + virtual ~HydraSigchldEvent(); + + private: + void OnIOEventReceived(int fd, int condition) override; + + private: + IEvent* listener_; + std::unique_ptr socket_; + std::unique_ptr channel_; + pid_t current_pid_ = getpid(); +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_HYDRA_SIGCHLD_EVENT_HH_ diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index cb240cc..8cde2e1 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -49,7 +49,6 @@ #include "launchpad-process-pool/launchpad_debug.h" #include "launchpad-process-pool/launchpad_inotify.h" #include "launchpad-process-pool/launchpad_io_channel.h" -#include "launchpad-process-pool/launchpad_signal.h" #include "launchpad-process-pool/loader_info.hh" #include "launchpad-process-pool/slot_info.h" #include "lib/common/inc/key.h" @@ -61,6 +60,7 @@ #include "launchpad-process-pool/dbus.hh" #include "launchpad-process-pool/log.hh" #include "launchpad-process-pool/memory_monitor.hh" +#include "launchpad-process-pool/signal_manager.hh" #include "launchpad-process-pool/worker.hh" #define AUL_PR_NAME 16 @@ -202,6 +202,7 @@ typedef request_t* request_h; typedef int (*request_handler)(request_h request); static void HandleMemoryStatusChangedEvent(bool low_memory); +static void HandleSigchld(pid_t pid); namespace { @@ -251,6 +252,13 @@ class MemoryManager : public launchpad::MemoryMonitor, } }; +class SigchldHandler : public launchpad::SignalManager::IEvent { + private: + void OnSigchldReceived(pid_t pid) override { + HandleSigchld(pid); + } +}; + int __sys_hwacc; std::unique_ptr loader_info_manager; std::unique_ptr app_defined_loader_info_manager; @@ -272,6 +280,7 @@ io_channel_h __launchpad_channel; int __client_fd = -1; launchpad::AsanAppChecker __asan_app_checker; std::unique_ptr cleaner; +SigchldHandler sigchld_handler; } // namespace @@ -841,7 +850,7 @@ static int __exec_loader_process(void* arg) { char** argv = static_cast(arg); char err_buf[1024]; - _signal_unblock_sigchld(); + launchpad::SignalManager::GetInst().UnblockSigchld(); _close_all_fds(); _setup_stdio(basename(argv[LOADER_ARG_PATH])); @@ -1418,8 +1427,7 @@ static int __exec_app_process(void* arg) { setenv("TIZEN_ASAN_ACTIVATION", "1", 1); } - _signal_unblock_sigchld(); - + launchpad::SignalManager::GetInst().UnblockSigchld(); _delete_sock_path(getpid(), getuid()); PERF("prepare exec - first done"); @@ -1639,7 +1647,7 @@ static bool __handle_hydra_event(int fd, io_condition_e cond, void* data) { return true; } -static void __handle_sigchild(int pid, void* user_data) { +static void HandleSigchld(pid_t pid) { char* appid = static_cast( g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid))); if (appid) { @@ -3328,13 +3336,7 @@ static int __before_loop(int argc, char** argv) { return -1; } - ret = _signal_init(); - if (ret < 0) { - _E("Failed to initialize signal"); - return -1; - } - - _signal_set_sigchld_cb(__handle_sigchild, nullptr); + launchpad::SignalManager::GetInst().SetEventListener(&sigchld_handler); ret = __init_launchpad_fd(argc, argv); if (ret != 0) { @@ -3416,7 +3418,7 @@ static void __after_loop(void) { if (__launchpad_channel) _io_channel_destroy(__launchpad_channel); - _signal_fini(); + launchpad::SignalManager::GetInst().Dispose(); __sequencer_fini(); } diff --git a/src/launchpad-process-pool/launchpad_signal.cc b/src/launchpad-process-pool/launchpad_signal.cc deleted file mode 100644 index 13b6a0a..0000000 --- a/src/launchpad-process-pool/launchpad_signal.cc +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (c) 2015 - 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_signal.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "launchpad-process-pool/launchpad_io_channel.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; -socket_h __sigchld_socket; -io_channel_h __sigchld_channel; -socket_h __hydra_sigchld_socket; -io_channel_h __hydra_sigchld_channel; -signal_sigchld_cb __callback; -void* __user_data; - -std::unique_ptr recycle_bin; - -} // namespace - -static gboolean __hydra_sigchld_recovery_cb(gpointer data); -static gboolean __sigchld_recovery_cb(gpointer data); - -static void __sigchld_action(int pid) { - launchpad::DBus::SendAppDeadSignal(pid); - recycle_bin->Add(std::make_shared(pid)); -} - -static int __check_permission(int pid) { - char buf[512] = { - 0, - }; - int ret; - - ret = _proc_get_attr(pid, buf, sizeof(buf)); - if (ret < 0) - return -1; - - if (!strcmp(buf, "User") || !strcmp(buf, "System") || - !strcmp(buf, "System::Privileged")) - return 0; - - _E("Permission denied. peer(%d:%s)", pid, buf); - return -1; -} - -static bool __hydra_sigchld_handler(int fd, - io_condition_e cond, - void* user_data) { - socket_h client_socket; - int caller_pid; - int pid = -1; - int ret; - - if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { - _E("fd(%d), io_condition(%d)", fd, cond); - g_idle_add(__hydra_sigchld_recovery_cb, nullptr); - return false; - } - - ret = _socket_accept(__hydra_sigchld_socket, &client_socket); - if (ret < 0) - return true; - - _socket_get_pid(client_socket, &caller_pid); - ret = __check_permission(caller_pid); - if (ret < 0) { - _socket_destroy(client_socket); - return true; - } - - ret = _socket_read(client_socket, &pid, sizeof(pid)); - _socket_destroy(client_socket); - if (ret < 0) { - _E("Failed to read process id. ret(%d)", ret); - return true; - } - - _W("[__SIGCHLD__] pid(%d)", pid); - __sigchld_action(pid); - - if (__callback) - __callback(pid, user_data); - - return true; -} - -static int __hydra_sigchld_init(void) { - char path[LAUNCHPAD_SOCKET_PATH_SIZE]; - io_channel_h channel; - socket_h socket; - int ret; - int fd; - - snprintf(path, sizeof(path), "/run/aul/daemons/%u/%s", getuid(), - HYDRA_SIGCHLD_SOCK); - ret = _socket_create(path, false, &socket); - if (ret < 0) - return ret; - - _socket_get_fd(socket, &fd); - - auto cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; - channel = _io_channel_create(fd, static_cast(cond), - __hydra_sigchld_handler, nullptr); - if (!channel) { - _socket_destroy(socket); - return -ENOMEM; - } - - _io_channel_set_close_on_destroy(channel, false); - - __hydra_sigchld_socket = socket; - __hydra_sigchld_channel = channel; - - return 0; -} - -static int __hydra_sigchld_fini(void) { - if (__hydra_sigchld_channel) - _io_channel_destroy(__hydra_sigchld_channel); - - if (__hydra_sigchld_socket) { - if (__pid != getpid()) - _socket_set_fd(__hydra_sigchld_socket, -1); - - _socket_destroy(__hydra_sigchld_socket); - } - - return 0; -} - -static bool __sigchld_handler(int fd, io_condition_e cond, void* user_data) { - struct signalfd_siginfo info; - pid_t child_pid; - pid_t child_pgid; - int status; - int ret; - - if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { - _E("fd(%d), io_condition(%d)", fd, cond); - g_idle_add(__sigchld_recovery_cb, nullptr); - return false; - } - - do { - ret = _socket_read(__sigchld_socket, &info, sizeof(info)); - if (ret < 0) - break; - - child_pgid = getpgid(info.ssi_pid); - _W("[__SIGCHLD__] pid(%d), pgid(%d), status(%d)", info.ssi_pid, child_pgid, - info.ssi_status); - - while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { - if (child_pid == child_pgid) - killpg(child_pgid, SIGKILL); - - __sigchld_action(child_pid); - } - - if (__callback) - __callback(info.ssi_pid, __user_data); - } while (ret == 0); - - return true; -} - -static int __signal_block_sigchld(void) { - int ret; - - sigemptyset(&__mask); - sigaddset(&__mask, SIGCHLD); - - ret = sigprocmask(SIG_BLOCK, &__mask, &__old_mask); - if (ret < 0) { - ret = -errno; - _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno); - return ret; - } - - return 0; -} - -static int __signal_get_sigchld_fd(void) { - int sfd; - - sfd = signalfd(-1, &__mask, SFD_NONBLOCK | SFD_CLOEXEC); - if (sfd < 0) { - sfd = -errno; - _E("signalfd() is failed. errno(%d)", errno); - return sfd; - } - - return sfd; -} - -int _signal_unblock_sigchld(void) { - int ret; - - ret = sigprocmask(SIG_SETMASK, &__old_mask, nullptr); - if (ret < 0) { - ret = -errno; - _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno); - return ret; - } - - return 0; -} - -static int __sigchld_init(void) { - io_channel_h channel; - socket_h socket; - int sfd; - int ret; - - sfd = __signal_get_sigchld_fd(); - if (sfd < 0) - return sfd; - - ret = _socket_create_with_fd(sfd, &socket); - if (ret < 0) { - close(sfd); - return ret; - } - - auto cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; - channel = _io_channel_create(sfd, static_cast(cond), - __sigchld_handler, nullptr); - if (!channel) { - _socket_destroy(socket); - return -ENOMEM; - } - _io_channel_set_close_on_destroy(channel, false); - - __sigchld_socket = socket; - __sigchld_channel = channel; - - return 0; -} - -static int __sigchld_fini(void) { - if (__sigchld_channel) - _io_channel_destroy(__sigchld_channel); - - if (__sigchld_socket) { - if (__pid != getpid()) - _socket_set_fd(__sigchld_socket, -1); - - _socket_destroy(__sigchld_socket); - } - - return 0; -} - -int _signal_set_sigchld_cb(signal_sigchld_cb callback, void* user_data) { - __callback = callback; - __user_data = user_data; - - return 0; -} - -static gboolean __hydra_sigchld_recovery_cb(gpointer data) { - int ret; - - __hydra_sigchld_fini(); - - ret = __hydra_sigchld_init(); - if (ret < 0) { - _E("Failed to recover hydra sigchld socket"); - abort(); - } else { - _W("[__RECOVERY__] Hydra SIGCHLD Socket"); - } - - return G_SOURCE_REMOVE; -} - -static gboolean __sigchld_recovery_cb(gpointer data) { - int ret; - - __sigchld_fini(); - - ret = __sigchld_init(); - if (ret < 0) { - _E("Failed to recover sigchld fd"); - abort(); - } else { - _W("[__RECOVERY__] SIGCHLD fd"); - } - - return G_SOURCE_REMOVE; -} - -int _signal_init(void) { - int ret; - int i; - - _D("SIGNAL_INIT"); - __pid = getpid(); - - ret = __signal_block_sigchld(); - if (ret < 0) - return ret; - - ret = __sigchld_init(); - if (ret < 0) - return ret; - - ret = __hydra_sigchld_init(); - if (ret < 0) - return ret; - - for (i = 0; i < _NSIG; ++i) { - switch (i) { - /* controlled by sys-assert package*/ - case SIGQUIT: - case SIGILL: - case SIGABRT: - case SIGBUS: - case SIGFPE: - case SIGSEGV: - case SIGPIPE: - break; - default: - signal(i, SIG_DFL); - break; - } - } - - recycle_bin.reset(new launchpad::Worker("RecycleBin+")); - return 0; -} - -void _signal_fini(void) { -#ifndef PRELOAD_ACTIVATE - int i; - - for (i = 0; i < _NSIG; ++i) - signal(i, SIG_DFL); -#endif - - _D("SIGNAL_FINI"); - recycle_bin.reset(); - _signal_set_sigchld_cb(nullptr, nullptr); - __hydra_sigchld_fini(); - __sigchld_fini(); - _signal_unblock_sigchld(); -} diff --git a/src/launchpad-process-pool/launchpad_signal.h b/src/launchpad-process-pool/launchpad_signal.h deleted file mode 100644 index dffd961..0000000 --- a/src/launchpad-process-pool/launchpad_signal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2016 - 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_SIGNAL_H__ -#define __LAUNCHPAD_SIGNAL_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef void (*signal_sigchld_cb)(int pid, void *user_data); - -int _signal_set_sigchld_cb(signal_sigchld_cb callback, void *user_data); - -int _signal_unblock_sigchld(void); - -int _signal_init(void); - -void _signal_fini(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __LAUNCHPAD_SIGNAL_H__ */ diff --git a/src/launchpad-process-pool/sigchld_event.cc b/src/launchpad-process-pool/sigchld_event.cc new file mode 100644 index 0000000..b53624b --- /dev/null +++ b/src/launchpad-process-pool/sigchld_event.cc @@ -0,0 +1,66 @@ +/* + * 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/sigchld_event.hh" + +#include +#include +#include +#include + +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { + +SigchldEvent::SigchldEvent(int sfd, IEvent* listener) + : socket_(new Socket(sfd)), + channel_(new IOChannel(sfd, IOChannel::IOCondition::IO_IN, this)), + listener_(listener) { + _W("SigchldEvent() ctor. sfd: %d", sfd); + channel_->SetCloseOnDestroy(false); +} + +SigchldEvent::~SigchldEvent() { + if (getpid() != current_pid_) + socket_->RemoveFd(); +} + +void SigchldEvent::OnIOEventReceived(int fd, int condition) { + struct signalfd_siginfo info; + pid_t child_pid; + int status; + int ret; + + do { + ret = socket_->Read(&info, sizeof(info)); + if (ret < 0) + break; + + pid_t child_pgid = getpgid(info.ssi_pid); + _W("[SIGCHLD] pid(%d), pgid(%d), status(%d)", + info.ssi_pid, child_pgid, info.ssi_status); + + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + + if (listener_ != nullptr) + listener_->OnSigchld(child_pid, status); + } + } while (ret == 0); +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/sigchld_event.hh b/src/launchpad-process-pool/sigchld_event.hh new file mode 100644 index 0000000..56765ed --- /dev/null +++ b/src/launchpad-process-pool/sigchld_event.hh @@ -0,0 +1,54 @@ +/* + * 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_SIGCHLD_EVENT_HH_ +#define LAUNCHPAD_PROCESS_POOL_SIGCHLD_EVENT_HH_ + +#include +#include +#include + +#include + +#include +#include + +namespace launchpad { + +class SigchldEvent : public IOChannel::IEvent { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnSigchld(pid_t pid, int status) = 0; + }; + + SigchldEvent(int sfd, IEvent* listener); + virtual ~SigchldEvent(); + + private: + void OnIOEventReceived(int fd, int condition) override; + + private: + std::unique_ptr socket_; + std::unique_ptr channel_; + IEvent* listener_; + pid_t current_pid_ = getpid(); +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_SIGCHLD_EVENT_HH_ diff --git a/src/launchpad-process-pool/signal_manager.cc b/src/launchpad-process-pool/signal_manager.cc new file mode 100644 index 0000000..943a022 --- /dev/null +++ b/src/launchpad-process-pool/signal_manager.cc @@ -0,0 +1,198 @@ +/* + * 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/signal_manager.hh" + +#include + +#include +#include +#include +#include + +#include "lib/common/inc/launchpad_common.h" + +#include "launchpad-process-pool/dbus.hh" +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { +namespace { + +namespace fs = std::filesystem; + +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 (!fs::exists(proc_path)) + _delete_sock_path(atoi(entry.path().filename().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_; +}; + +} // namespace + +SignalManager& SignalManager::GetInst() { + static SignalManager inst; + inst.Init(); + return inst; +} + +void SignalManager::Dispose() { + if (disposed_) + return; + + _W("BEGIN"); +#ifndef PRELOAD_ACTIVATE + for (int signo = 0; signo < _NSIG; ++signo) + signal(signo, SIG_DFL); +#endif // PRELOAD_ACTIVATE + + recycle_bin_.reset(); + hydra_sigchld_event_.reset(); + sigchld_event_.reset(); + disposed_ = true; + _W("END"); +} + +void SignalManager::Init() { + if (!disposed_) + return; + + _W("BEGIN"); + if (BlockSigchld() != 0) + return; + + int sfd = GetSigchldFd(); + if (sfd < 0) + return; + + sigchld_event_.reset(new SigchldEvent(sfd, this)); + hydra_sigchld_event_.reset(new HydraSigchldEvent(this)); + recycle_bin_.reset(new Worker("RecycleBin+")); + + for (int signo = 0; signo < _NSIG; ++signo) { + if (signo == SIGQUIT || + signo == SIGILL || + signo == SIGABRT || + signo == SIGBUS || + signo == SIGFPE || + signo == SIGSEGV || + signo == SIGPIPE) + continue; + + signal(signo, SIG_DFL); + } + + disposed_ = false; + _W("END"); +} + +void SignalManager::SetEventListener(SignalManager::IEvent* listener) { + listener_ = listener; +} + +void SignalManager::UnblockSigchld() { + if (sigprocmask(SIG_SETMASK, &old_mask_, nullptr) < 0) + _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno); +} + +SignalManager::~SignalManager() { + Dispose(); +} + +int SignalManager::BlockSigchld() { + sigemptyset(&mask_); + sigaddset(&mask_, SIGCHLD); + if (sigprocmask(SIG_BLOCK, &mask_, &old_mask_) < 0) { + int ret = -errno; + _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno); + return ret; + } + + return 0; +} + +int SignalManager::GetSigchldFd() { + int sfd = signalfd(-1, &mask_, SFD_NONBLOCK | SFD_CLOEXEC); + if (sfd < 0) { + sfd = -errno; + _E("signalfd() is failed. errno(%d)", errno); + } + + return sfd; +} + +void SignalManager::HandleSigchld(pid_t pid) { + DBus::SendAppDeadSignal(pid); + recycle_bin_->Add(std::make_shared(pid)); +} + +void SignalManager::OnSigchld(pid_t pid, int status) { + _W("pid: %d, status: %d", pid, status); + HandleSigchld(pid); +} + +void SignalManager::OnHydraSigchld(pid_t pid) { + _W("pid: %d", pid); + HandleSigchld(pid); +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/signal_manager.hh b/src/launchpad-process-pool/signal_manager.hh new file mode 100644 index 0000000..23bef10 --- /dev/null +++ b/src/launchpad-process-pool/signal_manager.hh @@ -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. + */ + +#ifndef LAUNCHPAD_PROCESS_POOL_SIGNAL_MANAGER_HH_ +#define LAUNCHPAD_PROCESS_POOL_SIGNAL_MANAGER_HH_ + +#include +#include +#include + +#include + +#include +#include +#include + +#include "launchpad-process-pool/hydra_sigchld_event.hh" +#include "launchpad-process-pool/sigchld_event.hh" +#include "launchpad-process-pool/worker.hh" + +namespace launchpad { + +class SignalManager : public SigchldEvent::IEvent, + public HydraSigchldEvent::IEvent { + public: + class IEvent { + public: + virtual ~IEvent() = default; + virtual void OnSigchldReceived(pid_t pid) = 0; + }; + + SignalManager(const SignalManager&) = delete; + SignalManager& operator = (const SignalManager&) = delete; + SignalManager(SignalManager&&) = delete; + SignalManager& operator = (SignalManager&&) = delete; + + static SignalManager& GetInst(); + void Dispose(); + + void SetEventListener(IEvent* listener); + void UnblockSigchld(); + + private: + SignalManager() = default; + ~SignalManager(); + + void Init(); + void HandleSigchld(pid_t pid); + int GetSigchldFd(); + int BlockSigchld(); + + void OnSigchld(pid_t pid, int status) override; + void OnHydraSigchld(pid_t pid) override; + + private: + bool disposed_ = true; + IEvent* listener_ = nullptr; + sigset_t mask_; + sigset_t old_mask_; + std::unique_ptr sigchld_event_; + std::unique_ptr hydra_sigchld_event_; + std::unique_ptr recycle_bin_; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_SIGNAL_MANAGER_HH_ diff --git a/src/lib/launchpad-common/peer_credentials.cc b/src/lib/launchpad-common/peer_credentials.cc new file mode 100644 index 0000000..c2ac128 --- /dev/null +++ b/src/lib/launchpad-common/peer_credentials.cc @@ -0,0 +1,54 @@ +/* + * 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-common/peer_credentials.hh" + +#include +#include + +#include "launchpad-common/log_private.hh" + +namespace launchpad { + +pid_t PeerCredentials::GetPid() const { + return pid_; +} + +uid_t PeerCredentials::GetUid() const { + return uid_; +} + +gid_t PeerCredentials::GetGid() const { + return gid_; +} + +PeerCredentials::PeerCredentials(pid_t pid, uid_t uid, gid_t gid) + : pid_(pid), uid_(uid), gid_(gid) { +} + +std::unique_ptr PeerCredentials::Get(int fd) { + struct ucred cred; + socklen_t len = sizeof(struct ucred); + int ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, + static_cast(&cred), &len); + if (ret != 0) { + _E("getsockopt() is failed. fd(%d), errno(%d)", fd, errno); + return nullptr; + } + + return std::make_unique(cred.pid, cred.uid, cred.gid); +} +} // namespace launchpad diff --git a/src/lib/launchpad-common/peer_credentials.hh b/src/lib/launchpad-common/peer_credentials.hh new file mode 100644 index 0000000..5387a03 --- /dev/null +++ b/src/lib/launchpad-common/peer_credentials.hh @@ -0,0 +1,48 @@ +/* + * 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 LIB_LAUNCHPAD_COMMON_PEER_CREDENTIALS_HH_ +#define LIB_LAUNCHPAD_COMMON_PEER_CREDENTIALS_HH_ + +#include + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace launchpad { + +class EXPORT_API PeerCredentials { + public: + PeerCredentials(pid_t pid, uid_t uid, gid_t gid); + virtual ~PeerCredentials() = default; + + static std::unique_ptr Get(int fd); + + pid_t GetPid() const; + uid_t GetUid() const; + gid_t GetGid() const; + + private: + pid_t pid_; + uid_t uid_; + gid_t gid_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_PEER_CREDENTIALS_HH_ diff --git a/src/lib/launchpad-common/socket.cc b/src/lib/launchpad-common/socket.cc new file mode 100644 index 0000000..bb6c152 --- /dev/null +++ b/src/lib/launchpad-common/socket.cc @@ -0,0 +1,103 @@ +/* + * 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-common/socket.hh" + +#include +#include +#include +#include +#include +#include +#include + +#include "launchpad-common/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const int MAX_RETRY_CNT = 2; + +} // namespace + +Socket::Socket(int fd) : fd_(fd) {} + +Socket::~Socket() { + Close(); +} + +void Socket::Close() { + if (fd_ > -1) { + close(fd_); + fd_ = -1; + } +} + +int Socket::Write(const void* buf, size_t size) { + const unsigned char* buffer = static_cast(buf); + size_t left = size; + + while (left) { + ssize_t bytes = write(fd_, buffer, left); + if (bytes < 0) { + int ret = -errno; + _E("Write() is failed. fd(%d), errno(%d)", fd_, errno); + return ret; + } + + left -= bytes; + buffer += bytes; + } + + return 0; +} + +int Socket::Read(void* buf, size_t size) { + unsigned char* buffer = static_cast(buf); + size_t left = size; + + while (left) { + ssize_t bytes = read(fd_, buffer, left); + if (bytes == 0) { + _W("EOF. fd(%d)", fd_); + return -EIO; + } + + if (bytes < 0) + return -errno; + + left -= bytes; + buffer += bytes; + } + + return 0; +} + +bool Socket::IsClosed() const { + return fd_ < 0; +} + +int Socket::GetFd() const { + return fd_; +} + +int Socket::RemoveFd() { + int fd = fd_; + fd_ = -1; + return fd; +} + +} // namespace launchpad diff --git a/src/lib/launchpad-common/socket.hh b/src/lib/launchpad-common/socket.hh new file mode 100644 index 0000000..3078e96 --- /dev/null +++ b/src/lib/launchpad-common/socket.hh @@ -0,0 +1,47 @@ +/* + * 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 LIB_LAUNCHPAD_COMMON_SOCKET_HH_ +#define LIB_LAUNCHPAD_COMMON_SOCKET_HH_ + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace launchpad { + +class EXPORT_API Socket { + public: + explicit Socket(int fd); + virtual ~Socket(); + Socket(const Socket&) = delete; + Socket& operator = (const Socket&) = delete; + + void Close(); + int Write(const void* buf, size_t size); + int Read(void* buf, size_t size); + bool IsClosed() const; + int GetFd() const; + int RemoveFd(); + + private: + int fd_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_SOCKET_HH_ -- 2.7.4 From bc0e4f65c35aff3f2ab4356192e21d406713a2a0 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 23 Mar 2023 04:13:25 +0000 Subject: [PATCH 06/16] Release version 0.26.0 Changes: - Add liblaunchpad-common library for launchpad daemons - Fix 64bit build error - Add to enable TIZEN_ASAN_ACTIVATION - Refactor launchpad logger - Modify FileMonitor class - Refactor launchpad dbus - Fix static analysis issues - Refactor launchpad worker - Remove cpplint warning messages - Refactor Memory Monitor - Refactor launchpad signal Change-Id: Ic6ff617adc69a9593a0b8383fdd99bebf306c4ff Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 13e65d8..de4a2ec 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.25.1 +Version: 0.26.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 739da200cd7d4c2fb05e4ca1e8a2b8574c2d78d5 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 23 Mar 2023 07:01:58 +0000 Subject: [PATCH 07/16] Fix build break issues - Use std::stringstream instead of std::sscanf() - Use unsigned long long instead of uint64_t Change-Id: Ib6b0f7cf28efbb478ca110ec107f7d55761dd976 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/launchpad.cc | 14 +++++++------- src/lib/launchpad-common/procfs.cc | 29 +++++++++++++++++++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 8cde2e1..4d9a8fb 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -111,8 +111,8 @@ typedef struct { char* loader_extra = nullptr; int detection_method = 0; int timeout_val = 0; - uint64_t cpu_total_time = 0; - uint64_t cpu_idle_time = 0; + unsigned long long cpu_total_time = 0; + unsigned long long cpu_idle_time = 0; int threshold = 0; int threshold_max = 0; int threshold_min = 0; @@ -300,8 +300,8 @@ static gboolean __logger_recovery_cb(gpointer data); static gboolean __handle_queuing_slots(gpointer data) { candidate_process_context_t* cpc; - uint64_t total = 0; - uint64_t idle = 0; + unsigned long long total = 0; + unsigned long long idle = 0; if (__sequencer.idle_checker > 0) return G_SOURCE_CONTINUE; @@ -901,7 +901,7 @@ static int __hydra_send_request(int fd, enum hydra_cmd cmd) { } sent += send_ret; - _D("send(%d: ret: %d) : %d / %d", fd, send_ret, sent, size); + _D("send(%d: ret: %zd) : %zd / %zd", fd, send_ret, sent, size); } return 0; @@ -1744,8 +1744,8 @@ static void __update_threshold(candidate_process_context_t* cpc, float delta) { } static gboolean __handle_idle_checker(gpointer data) { - uint64_t total = 0; - uint64_t idle = 0; + unsigned long long total = 0; + unsigned long long idle = 0; int per; candidate_process_context_t* cpc; diff --git a/src/lib/launchpad-common/procfs.cc b/src/lib/launchpad-common/procfs.cc index ac9596b..6fa2137 100644 --- a/src/lib/launchpad-common/procfs.cc +++ b/src/lib/launchpad-common/procfs.cc @@ -18,6 +18,8 @@ #include +#include +#include #include #include #include @@ -76,14 +78,29 @@ void Procfs::GetPssMemory(pid_t pid, uint64_t* mem_pss) { return; } - std::ifstream file("/proc/" + std::to_string(pid) + "/smaps"); - std::string line; - uint64_t total_pss = 0; + std::filesystem::path smaps_path = "/proc/" + std::to_string(pid) + "/smaps"; + if (!std::filesystem::exists(smaps_path)) { + _E("%s does not exist", smaps_path.c_str()); + return; + } + + std::ifstream file(smaps_path); + if (!file) { + _E("Failed to open %s", smaps_path.c_str()); + return; + } + uint64_t total_pss = 0; + std::string line; while (std::getline(file, line)) { - uint64_t pss = 0; - if (std::sscanf(line.c_str(), "Pss: %llu kB", &pss) == 1) - total_pss += pss; + std::stringstream stream(line); + std::string pss_str; + if (stream >> pss_str && pss_str == "Pss:") { + uint64_t pss = 0; + if (stream >> pss) { + total_pss += pss; + } + } } *mem_pss = total_pss; -- 2.7.4 From eb114ef1269e3c33932365eaa59b0a9485fe3123 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 23 Mar 2023 07:40:04 +0000 Subject: [PATCH 08/16] Release version 0.26.1 Changes: - Fix build break issues Change-Id: I104e968477b4d98acc3286e72fc2e671756851e4 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index de4a2ec..624d67f 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.26.0 +Version: 0.26.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 83fee9e0ca21cba0c1b15b0ba2e14ac0cad8d4cf Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 23 Mar 2023 08:48:27 +0000 Subject: [PATCH 09/16] Add CPUChecker and AppInfo classes The new claases are for refactoring the launchpad. Adds: - CPUChecker - AppInfo Change-Id: I1cb745057d34fc092783c172b3369ebd4bc39d9c Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/app_info.cc | 202 ++++++++++++++++++++++++++++++ src/launchpad-process-pool/app_info.hh | 109 ++++++++++++++++ src/launchpad-process-pool/cpu_checker.cc | 123 ++++++++++++++++++ src/launchpad-process-pool/cpu_checker.hh | 47 +++++++ 4 files changed, 481 insertions(+) create mode 100644 src/launchpad-process-pool/app_info.cc create mode 100644 src/launchpad-process-pool/app_info.hh create mode 100644 src/launchpad-process-pool/cpu_checker.cc create mode 100644 src/launchpad-process-pool/cpu_checker.hh diff --git a/src/launchpad-process-pool/app_info.cc b/src/launchpad-process-pool/app_info.cc new file mode 100644 index 0000000..d7e7c19 --- /dev/null +++ b/src/launchpad-process-pool/app_info.cc @@ -0,0 +1,202 @@ +/* + * 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/app_info.hh" + +#include + +#include "lib/common/inc/key.h" + +namespace launchpad { + +AppInfo::Builder& AppInfo::Builder::SetAppId(const tizen_base::Bundle& b) { + app_id_ = b.GetString(AUL_K_APPID); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetAppPath(const tizen_base::Bundle& b) { + app_path_ = b.GetString(AUL_K_EXEC); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetOriginalAppPath( + const tizen_base::Bundle& b) { + original_app_path_ = b.GetString(AUL_K_EXEC); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetPkgType(const tizen_base::Bundle& b) { + pkg_type_ = b.GetString(AUL_K_PACKAGETYPE); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetAppType(const tizen_base::Bundle& b) { + app_type_ = b.GetString(AUL_K_APP_TYPE); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetHwacc(const tizen_base::Bundle& b) { + hwacc_ = b.GetString(AUL_K_HWACC); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetTaskmanage(const tizen_base::Bundle& b) { + taskmanage_ = b.GetString(AUL_K_TASKMANAGE); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetPkgId(const tizen_base::Bundle& b) { + pkg_id_ = b.GetString(AUL_K_PKGID); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetCompType(const tizen_base::Bundle& b) { + comp_type_ = b.GetString(AUL_K_COMP_TYPE); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetInternalPool( + const tizen_base::Bundle& b) { + internal_pool_ = b.GetString(AUL_K_INTERNAL_POOL); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetRootPath(const tizen_base::Bundle& b) { + root_path_ = b.GetString(AUL_K_ROOT_PATH); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetLoaderName(const tizen_base::Bundle& b) { + loader_name_ = b.GetString(AUL_K_LOADER_NAME); + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetGlobal(const tizen_base::Bundle& b) { + if (b.GetString(AUL_K_IS_GLOBAL) == "true") + global_ = true; + else + global_ = false; + + return *this; +} + +AppInfo::Builder& AppInfo::Builder::SetBundle(tizen_base::Bundle b) { + b_ = std::move(b); + return *this; +} + +AppInfo::Builder::operator AppInfo*() { + return new (std::nothrow) AppInfo(std::move(app_id_), std::move(app_path_), + std::move(original_app_path_), std::move(pkg_type_), std::move(app_type_), + std::move(hwacc_), std::move(taskmanage_), std::move(pkg_id_), + std::move(comp_type_), std::move(internal_pool_), std::move(root_path_), + std::move(loader_name_), global_, std::move(b_)); +} + +std::unique_ptr AppInfo::Create(tizen_base::Bundle b) { + return std::unique_ptr(Builder().SetAppId(b) + .SetAppPath(b) + .SetOriginalAppPath(b) + .SetPkgType(b) + .SetAppType(b) + .SetHwacc(b) + .SetTaskmanage(b) + .SetPkgId(b) + .SetCompType(b) + .SetInternalPool(b) + .SetRootPath(b) + .SetLoaderName(b) + .SetGlobal(b) + .SetBundle(std::move(b))); +} + +const std::string& AppInfo::GetAppId() const { + return app_id_; +} + +const std::string& AppInfo::GetAppPath() const { + return app_path_; +} + +const std::string& AppInfo::GetOriginalAppPath() const { + return original_app_path_; +} + +const std::string& AppInfo::GetPkgType() const { + return pkg_type_; +} + +const std::string& AppInfo::GetAppType() const { + return app_type_; +} + +const std::string& AppInfo::GetHwacc() const { + return hwacc_; +} + +const std::string& AppInfo::GetTaskmanage() const { + return taskmanage_; +} + +const std::string& AppInfo::GetPkgId() const { + return pkg_id_; +} + +const std::string& AppInfo::GetCompType() const { + return comp_type_; +} + +const std::string& AppInfo::GetInternalPool() const { + return internal_pool_; +} + +const std::string& AppInfo::GetRootPath() const { + return root_path_; +} + +const std::string& AppInfo::GetLoaderName() const { + return loader_name_; +} + +const bool AppInfo::IsGlobal() const { + return global_; +} + +const tizen_base::Bundle& AppInfo::GetBundle() const { + return b_; +} + +AppInfo::AppInfo(std::string app_id, std::string app_path, + std::string original_app_path, std::string pkg_type, std::string app_type, + std::string hwacc, std::string taskmanage, std::string pkg_id, + std::string comp_type, std::string internal_pool, std::string root_path, + std::string loader_name, bool global, tizen_base::Bundle b) + : app_id_(std::move(app_id)), + app_path_(std::move(app_path)), + original_app_path_(std::move(original_app_path)), + pkg_type_(std::move(pkg_type)), + app_type_(std::move(app_type)), + hwacc_(std::move(hwacc)), + taskmanage_(std::move(taskmanage)), + pkg_id_(std::move(pkg_id)), + comp_type_(std::move(comp_type)), + internal_pool_(std::move(internal_pool)), + root_path_(std::move(root_path)), + loader_name_(std::move(loader_name)), + global_(global), + b_(std::move(b)) {} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/app_info.hh b/src/launchpad-process-pool/app_info.hh new file mode 100644 index 0000000..32c1675 --- /dev/null +++ b/src/launchpad-process-pool/app_info.hh @@ -0,0 +1,109 @@ +/* + * 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_APP_INFO_HH_ +#define LAUNCHPAD_PROCESS_POOL_APP_INFO_HH_ + +#include + +#include +#include + +namespace launchpad { + +class AppInfo { + public: + class Builder { + public: + Builder& SetAppId(const tizen_base::Bundle& b); + Builder& SetAppPath(const tizen_base::Bundle& b); + Builder& SetOriginalAppPath(const tizen_base::Bundle& b); + Builder& SetPkgType(const tizen_base::Bundle& b); + Builder& SetAppType(const tizen_base::Bundle& b); + Builder& SetHwacc(const tizen_base::Bundle& b); + Builder& SetTaskmanage(const tizen_base::Bundle& b); + Builder& SetPkgId(const tizen_base::Bundle& b); + Builder& SetCompType(const tizen_base::Bundle& b); + Builder& SetInternalPool(const tizen_base::Bundle& b); + Builder& SetRootPath(const tizen_base::Bundle& b); + Builder& SetLoaderName(const tizen_base::Bundle& b); + Builder& SetGlobal(const tizen_base::Bundle& b); + Builder& SetBundle(tizen_base::Bundle b); + operator AppInfo*(); + + private: + std::string app_id_; + std::string app_path_; + std::string original_app_path_; + std::string pkg_type_; + std::string app_type_; + std::string hwacc_; + std::string taskmanage_; + std::string pkg_id_; + std::string comp_type_; + std::string internal_pool_; + std::string root_path_; + std::string loader_name_; + bool global_; + tizen_base::Bundle b_; + }; + + virtual ~AppInfo() = default; + + static std::unique_ptr Create(tizen_base::Bundle b); + + const std::string& GetAppId() const; + const std::string& GetAppPath() const; + const std::string& GetOriginalAppPath() const; + const std::string& GetPkgType() const; + const std::string& GetAppType() const; + const std::string& GetHwacc() const; + const std::string& GetTaskmanage() const; + const std::string& GetPkgId() const; + const std::string& GetCompType() const; + const std::string& GetInternalPool() const; + const std::string& GetRootPath() const; + const std::string& GetLoaderName() const; + const bool IsGlobal() const; + const tizen_base::Bundle& GetBundle() const; + + private: + AppInfo(std::string app_id, std::string app_path, + std::string original_app_path, std::string pkg_type, std::string app_type, + std::string hwacc, std::string taskmanage, std::string pkg_id, + std::string comp_type, std::string internal_pool, std::string root_path, + std::string loader_name, bool global, tizen_base::Bundle b); + + private: + std::string app_id_; + std::string app_path_; + std::string original_app_path_; + std::string pkg_type_; + std::string app_type_; + std::string hwacc_; + std::string taskmanage_; + std::string pkg_id_; + std::string comp_type_; + std::string internal_pool_; + std::string root_path_; + std::string loader_name_; + bool global_; + tizen_base::Bundle b_; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_APP_INFO_HH_ diff --git a/src/launchpad-process-pool/cpu_checker.cc b/src/launchpad-process-pool/cpu_checker.cc new file mode 100644 index 0000000..3777f1c --- /dev/null +++ b/src/launchpad-process-pool/cpu_checker.cc @@ -0,0 +1,123 @@ +/* + * 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/cpu_checker.hh" + +#include +#include +#include +#include +#include + +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const float PI = 3.14159265; + +void GetCPUIdle(uint64_t* total, uint64_t* idle) { + std::ifstream stat_file("/proc/stat"); + if (!stat_file) { + _E("Failed to open /proc/stat"); + return; + } + + std::string cpu_label; + stat_file >> cpu_label; + if (cpu_label != "cpu") { + _E("Unexpected label in /proc/stat"); + return; + } + + uint64_t sum = 0; + uint64_t value; + uint64_t idle_value = 0; + for (int i = 0; i < 10; ++i) { + if (!(stat_file >> value)) { + _E("Failed to read /proc/stat"); + return; + } + + if (sum + value < sum) { + _E("Overflow in /proc/stat"); + return; + } + + sum += value; + if (i == 3) + idle_value = value; + } + + *total = sum; + *idle = idle_value; +} + +float Interpolator(float input, int cpu_max, int cpu_min) { + const float min_percent = cpu_min / 100.0f; + const float max_percent = cpu_max / 100.0f; + const float input_clamped = std::clamp(input, 0.0f, 1.0f); + const float result = (std::cos(input_clamped * PI) / 2.0f) + 0.5f; + return (result * (max_percent - min_percent)) - min_percent; +} + +} // namespace + +CPUChecker::CPUChecker(int threshold_max, int threshold_min) + : threshold_max_(threshold_max), + threshold_min_(threshold_min) { +} + +bool CPUChecker::IsIdle() { + uint64_t total; + uint64_t idle; + GetCPUIdle(&total, &idle); + + if (total == cpu_total_time_) + total++; + + auto percentage = CalculatePercentage(idle, total); + if (percentage >= threshold_) { + UpdateThreshold(-0.02f * (percentage - threshold_)); + return true; + } + + UpdateCPUIdleTime(idle); + UpdateCPUTotalTime(total); + UpdateThreshold(0.05f); + return false; +} + +float CPUChecker::CalculatePercentage(uint64_t idle, uint64_t total) { + return (idle - cpu_idle_time_) * 100 / (total - cpu_total_time_); +} + +void CPUChecker::UpdateCPUIdleTime(uint64_t idle) { + cpu_idle_time_ = idle; +} + +void CPUChecker::UpdateCPUTotalTime(uint64_t total) { + cpu_total_time_ = total; +} + +void CPUChecker::UpdateThreshold(float delta) { + pos_ = std::clamp(pos_ + delta, 0.0f, 1.0f); + threshold_ = Interpolator(pos_, threshold_max_, threshold_min_) * 100; + _D("[CPU] delta: %f, input cursor: %f, threshold: %f", + delta, pos_, threshold_); +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/cpu_checker.hh b/src/launchpad-process-pool/cpu_checker.hh new file mode 100644 index 0000000..6e23ed8 --- /dev/null +++ b/src/launchpad-process-pool/cpu_checker.hh @@ -0,0 +1,47 @@ +/* + * 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_CPU_CHECKER_HH_ +#define LAUNCHPAD_PROCESS_POOL_CPU_CHECKER_HH_ + +#include + +namespace launchpad { + +class CPUChecker { + public: + CPUChecker(int threshold_max, int threshold_min); + + bool IsIdle(); + + private: + float CalculatePercentage(uint64_t idle, uint64_t total); + void UpdateCPUIdleTime(uint64_t idle); + void UpdateCPUTotalTime(uint64_t total); + void UpdateThreshold(float delta); + + private: + int threshold_max_; + int threshold_min_; + uint64_t cpu_idle_time_ = 0; + uint64_t cpu_total_time_ = 0; + float threshold_ = 0; + float pos_ = 0.0f; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_CPU_CHECKER_HH_ -- 2.7.4 From 2fc946c83e2d3c505be7f54a10808aa453858575 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 24 Mar 2023 05:13:21 +0000 Subject: [PATCH 10/16] Refactor launchpad debug The launchpad debug is implemented using C++ language. Change-Id: I13ed4cb60cfcf356d52748d3a2f3d53182ca2d23 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/debug.cc | 267 ++++++++++++- src/launchpad-process-pool/debug.hh | 60 ++- src/launchpad-process-pool/debugger_info.cc | 167 +++++---- src/launchpad-process-pool/debugger_info.hh | 20 +- src/launchpad-process-pool/launchpad.cc | 213 +++-------- src/launchpad-process-pool/launchpad_debug.cc | 413 --------------------- src/launchpad-process-pool/launchpad_debug.h | 40 -- src/launchpad-process-pool/util.cc | 16 +- src/launchpad-process-pool/util.hh | 10 +- .../src/test_launchpad.cc | 6 +- 10 files changed, 479 insertions(+), 733 deletions(-) delete mode 100644 src/launchpad-process-pool/launchpad_debug.cc delete mode 100644 src/launchpad-process-pool/launchpad_debug.h diff --git a/src/launchpad-process-pool/debug.cc b/src/launchpad-process-pool/debug.cc index 0d2f90b..4d70c91 100644 --- a/src/launchpad-process-pool/debug.cc +++ b/src/launchpad-process-pool/debug.cc @@ -16,15 +16,268 @@ #include "launchpad-process-pool/debug.hh" +#include +#include +#include +#include +#include + #include +#include +#include "lib/common/inc/key.h" #include "lib/common/inc/launchpad_common.h" +namespace fs = std::filesystem; + namespace launchpad { +namespace { + +constexpr const char kAsanAppListPath[] = + "/opt/usr/share/aul/debug/.asan_app_list"; +constexpr const char kDebuggerInfoPath[] = "/run/share/aul"; + +std::vector GetStringArray(const tizen_base::Bundle& b, + const std::string& key) { + std::vector values; + if (b.GetType(key) & BUNDLE_TYPE_ARRAY) { + values = b.GetStringArray(key); + } else { + std::string value = b.GetString(key); + if (!value.empty()) + values.push_back(std::move(value)); + } + + return values; +} + +} // namespace + +Debug& Debug::GetInst() { + static Debug inst; + inst.Init(); + return inst; +} + +void Debug::Dispose() { + if (disposed_) + return; + + file_monitor_.reset(); + disposed_ = true; +} + +void Debug::Load() { + if (!debugger_infos_.empty()) + return; + + DebuggerInfoInflator inflator; + debugger_infos_ = inflator.Inflate(kDebuggerInfoPath); +} + +void Debug::PrepareDebugger(const tizen_base::Bundle& b) { + auto debugger = b.GetString(AUL_K_SDK); + if (debugger.empty()) + return; + + _D("[DEBUG] Debugger: %s", debugger.c_str()); + auto found = debugger_infos_.find(debugger); + if (found == debugger_infos_.end()) + return; + + debugger_info_ = found->second; + if (debugger == "ASAN") + setenv("TIZEN_ASAN_ACTIVATION", "1", 1); + + ParseAndRedirectStandardFds(b); + RemoveFiles(debugger_info_->GetUnlinkList()); + + for (const auto& extra_env : debugger_info_->GetExtraEnvList()) + ParseAndSetEnvironment(b, extra_env); + + debug_argv_ = debugger_info_->GetDefaultOptList(); + debug_argv_.insert(debug_argv_.begin(), debugger_info_->GetExe()); + for (const auto& extra_key : debugger_info_->GetExtraKeyList()) + ParseAndAddArgv(b, extra_key); + + for (const auto& last_extra_key : debugger_info_->GetLastExtraKeyList()) + ParseAndAddExtraArgv(b, last_extra_key); +} + +void Debug::ChangeMountNamespace() { + auto target_pid = std::getenv("TARGET_PID"); + if (target_pid == nullptr) + return; + + std::string mnt_path = "/proc/" + std::string(target_pid) + "/ns/mnt"; + int fd = open(mnt_path.c_str(), O_RDONLY); + if (fd < 0) { + _E("open() is failed. path(%s), errno(%d)", mnt_path.c_str(), errno); + return; + } + + int ret = ::setns(fd, CLONE_NEWNS); + close(fd); + if (ret != 0) { + _E("setns() is failed. errno(%d)", errno); + return; + } + + _D("setns() is successful"); +} + +void Debug::CheckWebAppDebugging(const tizen_base::Bundle& b) { + if (b.GetType(AUL_K_DEBUG) != BUNDLE_TYPE_NONE) + setenv("TIZEN_DEBUGGING_PORT", "1", 1); +} + +bool Debug::CheckAsanApp(const std::string& appid) { + return asan_app_map_.find(appid) != asan_app_map_.end(); +} + +void Debug::CheckAndSetAsanActivation(const std::string& appid) { + if (CheckAsanApp(appid)) { + _W("Set TIZEN_ASAN_ACTIVATION. appid: %s", appid.c_str()); + setenv("TIZEN_ASAN_ACTIVATION", "1", 1); + } +} + +std::vector Debug::GetExtraArgv() const { + return extra_argv_; +} + +std::vector Debug::GetArgv() const { + return debug_argv_; +} + +bool Debug::ShouldAttach() const { + if (!debugger_info_) + return false; + + return debugger_info_->GetAttachInfo() == "true"; +} + +Debug::~Debug() { + Dispose(); +} + +void Debug::Init() { + if (!disposed_) + return; + + file_monitor_ = std::make_unique(kAsanAppListPath, this); + disposed_ = false; +} + +void Debug::RemoveFiles(const std::vector& files) { + for (const auto& file : files) { + if (fs::exists(file)) { + _D("[DEBUG] file: %s", file.c_str()); + fs::remove(file); + } + } +} + +void Debug::ParseAndSetEnvironment(const tizen_base::Bundle& b, + const std::string& key) { + _D("[DEBUG] key: %s", key.c_str()); + std::vector values = GetStringArray(b, key); + if (values.empty()) + return; + + std::string env; + for (const auto& value : values) { + if (!env.empty()) + env += ","; + + env += value; + } + + const_cast(b).Delete(key); + _D("[DEBUG] value: %s", env.c_str()); + setenv(key.c_str(), env.c_str(), 1); +} + +void Debug::ParseAndAddArgv(const tizen_base::Bundle& b, + const std::string& key) { + _D("[DEBUG] key: %s", key.c_str()); + std::vector values = GetStringArray(b, key); + if (values.empty()) + return; + + for (const auto& arg : values) { + debug_argv_.push_back(arg); + if (key == "__DLP_ATTACH_ARG__" && isdigit(arg[0])) { + _D("[DEBUG] TARGET_PID: %s", arg.c_str()); + setenv("TARGET_PID", arg.c_str(), 1); + } + } + + const_cast(b).Delete(key); +} + +void Debug::ParseAndAddExtraArgv(const tizen_base::Bundle& b, + const std::string& key) { + _D("[DEBUG] key: %s", key.c_str()); + std::vector values = GetStringArray(b, key); + if (values.empty()) return; + + for (const auto& arg : values) + extra_argv_.push_back(arg); + + const_cast(b).Delete(key); +} + +void Debug::ParseAndRedirectStandardFds(const tizen_base::Bundle& b) { + pid_t caller_pid = GetCallerPid(b); + if (caller_pid < 0) + return; + + // stdin + std::string path = "/proc/" + std::to_string(caller_pid) + "/fd/"; + int fd = open((path + std::to_string(STDIN_FILENO)).c_str(), O_RDONLY); + if (fd < 0) { + _E("Failed to open STDIN file descriptor. errno(%d)", errno); + return; + } + + dup2(fd, STDIN_FILENO); + close(fd); + + // stdout + fd = open((path + std::to_string(STDOUT_FILENO)).c_str(), O_WRONLY); + if (fd < 0) { + _E("Failed to open STDOUT file descriptor. errno(%d)", errno); + return; + } + + dup2(fd, STDOUT_FILENO); + close(fd); + + // stdout + fd = open((path + std::to_string(STDERR_FILENO)).c_str(), O_WRONLY); + if (fd < 0) { + _E("Failed to open STDERR file descriptor. errno(%d)", errno); + return; + } + + dup2(fd, STDERR_FILENO); + close(fd); +} + +pid_t Debug::GetCallerPid(const tizen_base::Bundle& b) { + auto pid_str = b.GetString(AUL_K_ORG_CALLER_PID); + if (pid_str.empty()) + pid_str = b.GetString(AUL_K_CALLER_PID); -AsanAppChecker::AsanAppChecker() : file_monitor_(kAsanAppListPath, this) {} + if (pid_str.empty()) + return -1; -void AsanAppChecker::Update() { + return std::stoi(pid_str); +} + +void Debug::OnFileChanged(FileMonitor::FileMonitorEvent event) { + _W("%s was changed. event(%d)", kAsanAppListPath, static_cast(event)); asan_app_map_.clear(); std::ifstream if_stream; if_stream.open(kAsanAppListPath); @@ -40,14 +293,4 @@ void AsanAppChecker::Update() { } } -bool AsanAppChecker::CheckAsanApp(const std::string& appid) const { - return asan_app_map_.find(appid) != asan_app_map_.end(); -} - -void AsanAppChecker::OnFileChanged( - launchpad::FileMonitor::FileMonitorEvent event) { - _W("%s was changed. event(%d)", kAsanAppListPath, static_cast(event)); - Update(); -} - } // namespace launchpad diff --git a/src/launchpad-process-pool/debug.hh b/src/launchpad-process-pool/debug.hh index d0ae3a1..48212d0 100644 --- a/src/launchpad-process-pool/debug.hh +++ b/src/launchpad-process-pool/debug.hh @@ -14,31 +14,69 @@ * limitations under the License. */ -#ifndef DEBUG_HH_ -#define DEBUG_HH_ +#ifndef LAUNCHPAD_PROCESS_POOL_DEBUG_HH_ +#define LAUNCHPAD_PROCESS_POOL_DEBUG_HH_ +#include + +#include +#include #include +#include #include +#include -#include +#include "launchpad-process-pool/debugger_info.hh" +#include "launchpad-process-pool/file_monitor.hh" namespace launchpad { -class AsanAppChecker : public launchpad::FileMonitor::IEvent { +class Debug : public FileMonitor::IEvent { public: - AsanAppChecker(); - bool CheckAsanApp(const std::string& appid) const; + Debug(const Debug&) = delete; + Debug& operator = (const Debug&) = delete; + Debug(Debug&&) = delete; + Debug& operator = (Debug&&) = delete; + + static Debug& GetInst(); + void Init(); + void Dispose(); + void Load(); + void PrepareDebugger(const tizen_base::Bundle& b); + std::vector GetExtraArgv() const; + std::vector GetArgv() const; + bool ShouldAttach() const; + bool CheckAsanApp(const std::string& appid); + void CheckAndSetAsanActivation(const std::string& appid); + + static void ChangeMountNamespace(); + static void CheckWebAppDebugging(const tizen_base::Bundle& b); private: - void Update(); + Debug() = default; + ~Debug(); + + void RemoveFiles(const std::vector& files); + void ParseAndSetEnvironment( + const tizen_base::Bundle& b, const std::string& key); + void ParseAndAddArgv(const tizen_base::Bundle& b, const std::string& key); + void ParseAndAddExtraArgv(const tizen_base::Bundle& b, + const std::string& key); + void ParseAndRedirectStandardFds(const tizen_base::Bundle& b); + pid_t GetCallerPid(const tizen_base::Bundle& b); + void OnFileChanged(launchpad::FileMonitor::FileMonitorEvent event) override; + private: + bool disposed_ = true; + DebuggerInfoPtr debugger_info_; + std::unordered_map debugger_infos_; + std::vector debug_argv_; + std::vector extra_argv_; std::unordered_set asan_app_map_; - static constexpr const char kAsanAppListPath[] = - "/opt/usr/share/aul/debug/.asan_app_list"; - launchpad::FileMonitor file_monitor_; + std::unique_ptr file_monitor_; }; } // namespace launchpad -#endif // DEBUG_HH_ +#endif // LAUNCHPAD_PROCESS_POOL_DEBUG_HH_ diff --git a/src/launchpad-process-pool/debugger_info.cc b/src/launchpad-process-pool/debugger_info.cc index 5ae58bd..b82890f 100644 --- a/src/launchpad-process-pool/debugger_info.cc +++ b/src/launchpad-process-pool/debugger_info.cc @@ -50,82 +50,6 @@ constexpr const char kTagDefaultOpt[] = "DEFAULT_OPT"; namespace fs = std::filesystem; -void DebuggerInfoInflator::Parse( - std::vector& debugger_info_list, - const fs::path& path) { - std::ifstream fp; - fp.open(path); - if (fp.fail()) - return; - - DebuggerInfoPtr info; - std::string input; - while (std::getline(fp, input)) { - std::istringstream ss(input); - std::string tok1, tok2; - if (!(ss >> tok1)) - continue; - - if (strcasecmp(kTagDebugger, tok1.c_str()) == 0) { - if (info != nullptr) { - _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str()); - debugger_info_list.push_back(std::move(info)); - } - - info = std::make_unique(); - continue; - } - - if (!(ss >> tok2)) - continue; - if (tok1.front() == '#' || info == nullptr) - continue; - - std::string key; - std::transform(tok1.begin(), tok1.end(), std::back_inserter(key), - [](char ch) { return toupper(ch); }); - if (kTagName == key) { - info->name_ = std::move(tok2); - } else if (kTagExe == key) { - fs::path file(tok2); - if (fs::exists(file) == false) { - _E("Failed to access %s", tok2.c_str()); - info.reset(); - continue; - } - - info->exe_ = std::move(tok2); - } else if (kTagAppType == key) { - std::string line = std::move(tok2); - do { - auto tokens = Split(line, " |\t\r\n"); - for (auto& token : tokens) { - _E("types: %s", token.c_str()); - info->app_types_.push_back(std::move(token)); - } - } while (std::getline(ss, line)); - } else if (kTagExtraKey == key) { - info->extra_key_list_.push_back(std::move(tok2)); - } else if (kTagExtraEnv == key) { - info->extra_env_list_.push_back(std::move(tok2)); - } else if (kTagUnlink == key) { - info->unlink_list_.push_back(std::move(tok2)); - } else if (kTagAttach == key) { - info->attach_ = std::move(tok2); - } else if (kTagLastExtraKey == key) { - info->last_extra_key_list_.push_back(std::move(tok2)); - } else if (kTagDefaultOpt == key) { - info->default_opt_list_.push_back(std::move(tok2)); - } - } - - fp.close(); - if (info) { - _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str()); - debugger_info_list.push_back(std::move(info)); - } -} - const std::string& DebuggerInfo::GetName() const { return name_; } @@ -162,20 +86,95 @@ const std::vector& DebuggerInfo::GetDefaultOptList() const { return default_opt_list_; } -std::vector DebuggerInfoInflator::Inflate( +std::unordered_map DebuggerInfoInflator::Inflate( const std::string_view path) { - fs::path p(path); - if (fs::is_directory(p) == false) - return {}; + fs::path input_path(path); + if (fs::is_directory(input_path) == false) + return debugger_infos_; - std::vector result; - for (auto& entry : fs::directory_iterator(p)) { + for (auto& entry : fs::directory_iterator(input_path)) { fs::path file(entry.path()); if (file.extension() == ".debugger") - Parse(result, file); + Parse(file); + } + + return debugger_infos_; +} + +void DebuggerInfoInflator::Parse(const fs::path& path) { + std::ifstream input_file(path); + if (!input_file.is_open()) + return; + + DebuggerInfoPtr current_info; + std::string input; + while (std::getline(input_file, input)) { + std::istringstream ss(input); + std::string token1; + if (!(ss >> token1)) + continue; + + std::string key = ToUpper(token1); + if (key == kTagDebugger) { + if (current_info != nullptr) + InsertDebuggerInfo(std::move(current_info)); + + current_info = std::make_unique(); + continue; + } + + if (key.front() == '#' || current_info == nullptr) + continue; + + std::string token2; + if (!(ss >> token2)) + continue; + + if (key == kTagName) { + current_info->name_ = std::move(token2); + } else if (key == kTagExe) { + current_info->exe_ = std::move(token2); + } else if (key == kTagAppType) { + ParseAndSetAppTypes(current_info.get(), ss, std::move(token2)); + } else if (key == kTagExtraKey) { + current_info->extra_key_list_.push_back(std::move(token2)); + } else if (key == kTagExtraEnv) { + current_info->extra_env_list_.push_back(std::move(token2)); + } else if (key == kTagUnlink) { + current_info->unlink_list_.push_back(std::move(token2)); + } else if (key == kTagAttach) { + current_info->attach_ = std::move(token2); + } else if (key == kTagLastExtraKey) { + current_info->last_extra_key_list_.push_back(std::move(token2)); + } else if (key == kTagDefaultOpt) { + current_info->default_opt_list_.push_back(std::move(token2)); + } } - return result; + if (current_info != nullptr) + InsertDebuggerInfo(std::move(current_info)); + + input_file.close(); +} + +void DebuggerInfoInflator::ParseAndSetAppTypes(DebuggerInfo* info, + std::istringstream& ss, std::string line) { + do { + auto tokens = Split(line, " |\t\r\n"); + for (auto& token : tokens) { + _D("app-type: %s", token.c_str()); + info->app_types_.push_back(std::move(token)); + } + } while (std::getline(ss, line)); +} + +void DebuggerInfoInflator::InsertDebuggerInfo(DebuggerInfoPtr info) { + if (debugger_infos_.find(info->name_) != debugger_infos_.end()) + return; + + _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str()); + std::string name = info->name_; + debugger_infos_[std::move(name)] = std::move(info); } } // namespace launchpad diff --git a/src/launchpad-process-pool/debugger_info.hh b/src/launchpad-process-pool/debugger_info.hh index 83a578d..b02bdb1 100644 --- a/src/launchpad-process-pool/debugger_info.hh +++ b/src/launchpad-process-pool/debugger_info.hh @@ -14,13 +14,14 @@ * limitations under the License. */ -#ifndef DEBUGGER_INFO_HH_ -#define DEBUGGER_INFO_HH_ +#ifndef LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_ +#define LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_ #include #include #include #include +#include #include namespace launchpad { @@ -55,12 +56,19 @@ using DebuggerInfoPtr = std::shared_ptr; class DebuggerInfoInflator { public: - std::vector Inflate(const std::string_view path); + std::unordered_map Inflate( + const std::string_view path); + + private: + void Parse(const std::filesystem::path& path); + void ParseAndSetAppTypes(DebuggerInfo* info, std::istringstream& ss, + std::string line); + void InsertDebuggerInfo(DebuggerInfoPtr info); + private: - void Parse(std::vector& debugger_info_list, - const std::filesystem::path& path); + std::unordered_map debugger_infos_; }; } // namespace launchpad -#endif // DEBUGGER_INFO_HH_ +#endif // LAUNCHPAD_PROCESS_POOL_DEBUGGER_INFO_HH_ diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 4d9a8fb..1acda44 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -43,13 +43,10 @@ #include -#include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/launcher_info.hh" #include "launchpad-process-pool/launchpad_config.h" -#include "launchpad-process-pool/launchpad_debug.h" #include "launchpad-process-pool/launchpad_inotify.h" #include "launchpad-process-pool/launchpad_io_channel.h" -#include "launchpad-process-pool/loader_info.hh" #include "launchpad-process-pool/slot_info.h" #include "lib/common/inc/key.h" #include "lib/common/inc/launchpad_common.h" @@ -57,7 +54,9 @@ #include "lib/common/inc/launchpad_types.h" #include "lib/common/inc/perf.h" +#include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/dbus.hh" +#include "launchpad-process-pool/loader_info.hh" #include "launchpad-process-pool/log.hh" #include "launchpad-process-pool/memory_monitor.hh" #include "launchpad-process-pool/signal_manager.hh" @@ -278,7 +277,6 @@ io_channel_h __logger_channel; io_channel_h __label_monitor_channel; io_channel_h __launchpad_channel; int __client_fd = -1; -launchpad::AsanAppChecker __asan_app_checker; std::unique_ptr cleaner; SigchldHandler sigchld_handler; @@ -1154,170 +1152,73 @@ static int __normal_fork_exec(int argc, char** argv, const char* app_path) { return 0; } -static int __create_launcher_argv(int* argc, char*** argv, - const char* app_type) { - int launcher_argc; - char** launcher_argv; - launchpad::LauncherInfoPtr launcher_info; - const char* exe; - int i; - - auto it = std::find_if( - launcher_info_list.begin(), launcher_info_list.end(), +static std::vector GetLauncherArgv( + const std::string& app_type) { + std::vector argv; + auto found = std::find_if(launcher_info_list.begin(), + launcher_info_list.end(), [app_type](const launchpad::LauncherInfoPtr& info) -> bool { return std::find_if(info->GetAppTypes().begin(), - info->GetAppTypes().end(), - [app_type](const std::string& type) -> bool { - return strcmp(type.c_str(), app_type) == 0; - }) != info->GetAppTypes().end(); + info->GetAppTypes().end(), + [app_type](const std::string& type) -> bool { + return type == app_type; + }) != info->GetAppTypes().end(); }); + if (found == launcher_info_list.end()) + return argv; - if (it == launcher_info_list.end()) - return 0; - - launcher_info = *it; - exe = launcher_info->GetExe().c_str(); - - auto& extra_args = launcher_info->GetExtraArgs(); - launcher_argc = extra_args.size() + 1; - launcher_argv = static_cast(calloc(launcher_argc, sizeof(char*))); - if (launcher_argv == nullptr) { - _E("out of memory"); - return -1; - } - - i = LOADER_ARG_PATH; - launcher_argv[i++] = strdup(exe); - - for (auto& extra_arg : extra_args) { - launcher_argv[i++] = strdup(extra_arg.c_str()); - } - - *argc = launcher_argc; - *argv = launcher_argv; - - return 0; -} - -static void __destroy_launcher_argv(int argc, char** argv) { - int i; - - if (argv == nullptr) - return; - - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); + auto launcher_info = *found; + argv.insert(argv.end(), launcher_info->GetExe()); + argv.insert(argv.end(), launcher_info->GetExtraArgs().begin(), + launcher_info->GetExtraArgs().end()); + return argv; } -static int __create_app_argv(int* argc, char*** argv, const char* app_path, - bundle* kb, const char* app_type) { - int new_argc; - char** new_argv; - bool attach = false; - struct app_arg debug_arg = { 0, }; - struct app_arg launcher_arg = { 0, }; - struct app_arg arg = { 0, }; - struct app_arg debug_extra_arg = { 0, }; - int ret; - int i; - int c; - - ret = _debug_create_argv(&debug_arg.argc, &debug_arg.argv, &attach); - if (ret < 0) { - _E("Failed to create debugger argv"); - return -1; - } - - if (attach) { - *argc = debug_arg.argc; - *argv = debug_arg.argv; - return 0; - } +static std::vector CreateAppArgv(const std::string& app_path, + const tizen_base::Bundle& b, const std::string& app_type) { + auto& inst = launchpad::Debug::GetInst(); + std::vector argv = inst.GetArgv(); + if (inst.ShouldAttach()) + return argv; - ret = _debug_create_extra_argv(&debug_extra_arg.argc, &debug_extra_arg.argv); - if (ret < 0) { - _E("Failed to create debugger extra argv"); - _debug_destroy_argv(debug_arg.argc, debug_arg.argv); - return -1; - } + auto launcher_argv = GetLauncherArgv(app_type); + if (!launcher_argv.empty()) + argv.insert(argv.end(), launcher_argv.begin(), launcher_argv.end()); - ret = - __create_launcher_argv(&launcher_arg.argc, &launcher_arg.argv, app_type); - if (ret < 0) { - _E("Failed to create launcher argv"); - _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv); - _debug_destroy_argv(debug_arg.argc, debug_arg.argv); - return -1; - } + auto exported_argv = b.Export(); + exported_argv[LOADER_ARG_PATH] = app_path; + if (!exported_argv.empty()) + argv.insert(argv.end(), exported_argv.begin(), exported_argv.end()); - arg.argc = bundle_export_to_argv(kb, &arg.argv); - if (arg.argc <= 0) { - _E("Failed to export bundle"); - __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv); - _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv); - _debug_destroy_argv(debug_arg.argc, debug_arg.argv); - return -1; - } - arg.argv[LOADER_ARG_PATH] = strdup(app_path); - - new_argc = - debug_arg.argc + launcher_arg.argc + arg.argc + debug_extra_arg.argc; - if (new_argc == arg.argc) { - *argc = arg.argc; - *argv = arg.argv; - return 0; - } + auto extra_argv = inst.GetExtraArgv(); + if (!extra_argv.empty()) + argv.insert(argv.end(), extra_argv.begin(), extra_argv.end()); - new_argv = reinterpret_cast(calloc(new_argc + 1, sizeof(char*))); - if (new_argv == nullptr) { - _E("out of memory"); - free(arg.argv[LOADER_ARG_PATH]); - bundle_free_exported_argv(arg.argc, &arg.argv); - __destroy_launcher_argv(launcher_arg.argc, launcher_arg.argv); - _debug_destroy_argv(debug_extra_arg.argc, debug_extra_arg.argv); - _debug_destroy_argv(debug_arg.argc, debug_arg.argv); - return -1; - } - - c = static_cast(LOADER_ARG_PATH); - for (i = 0; i < debug_arg.argc; i++) - new_argv[c++] = debug_arg.argv[i]; - for (i = 0; i < launcher_arg.argc; i++) - new_argv[c++] = launcher_arg.argv[i]; - for (i = 0; i < arg.argc; i++) - new_argv[c++] = arg.argv[i]; - for (i = 0; i < debug_extra_arg.argc; i++) - new_argv[c++] = debug_extra_arg.argv[i]; - - *argc = new_argc; - *argv = new_argv; - - return 0; + return argv; } static void __real_launch(const char* app_path, bundle* kb, appinfo_t* menu_info) { - int app_argc = 0; - char** app_argv; - int i; - int ret; - - if (bundle_get_val(kb, AUL_K_DEBUG) != nullptr) - setenv("TIZEN_DEBUGGING_PORT", "1", 1); + tizen_base::Bundle b(kb, false, false); + launchpad::Debug::CheckWebAppDebugging(b); - ret = __create_app_argv(&app_argc, &app_argv, app_path, kb, - menu_info->app_type); - if (ret < 0) { - _E("Failed to create app argv"); + std::vector argv = CreateAppArgv(app_path, b, + menu_info->app_type); + char** app_argv = static_cast(calloc(argv.size() + 1, sizeof(char*))); + if (app_argv == nullptr) { + _E("Out of memory"); exit(-1); } - for (i = 0; i < app_argc; i++) + int app_argc = argv.size(); + for (int i = 0; i < app_argc; i++) { + app_argv[i] = const_cast(argv[i].c_str()); SECURE_LOGD("input argument %d : %s##", i, app_argv[i]); + } PERF("setup argument done"); __normal_fork_exec(app_argc, app_argv, app_path); + free(app_argv); } static int __prepare_exec(const char* appid, const char* app_path, @@ -1358,7 +1259,7 @@ static int __prepare_exec(const char* appid, const char* app_path, return PAD_ERR_FAILED; if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) - _debug_change_mount_namespace(); + launchpad::Debug::ChangeMountNamespace(); /* SET PRIVILEGES*/ enabled_light_user = bundle_get_val(kb, AUL_K_ENABLED_LIGHT_USER); @@ -1419,13 +1320,11 @@ static int __exec_app_process(void* arg) { PERF("fork done"); _D("lock up test log(no error) : fork done"); - if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) - _debug_prepare_debugger(launch_arg->kb); + tizen_base::Bundle b(launch_arg->kb, false, false); + if (b.GetType(AUL_K_SDK) != BUNDLE_TYPE_NONE) + launchpad::Debug::GetInst().PrepareDebugger(b); - if (__asan_app_checker.CheckAsanApp(launch_arg->appid)) { - _W("%s TIZEN_ASAN_ACTIVATION", launch_arg->appid); - setenv("TIZEN_ASAN_ACTIVATION", "1", 1); - } + launchpad::Debug::GetInst().CheckAndSetAsanActivation(launch_arg->appid); launchpad::SignalManager::GetInst().UnblockSigchld(); _delete_sock_path(getpid(), getuid()); @@ -2493,7 +2392,7 @@ static void __handle_direct_launch(request_h request) { static void __fork_processing(request_h request) { if (bundle_get_type(request->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) - _debug_init(); + launchpad::Debug::GetInst().Load(); _W("appid: %s", request->menu_info->appid); request->pid = __launch_directly(request->menu_info->appid, request->app_path, @@ -2510,7 +2409,7 @@ static void __fork_processing(request_h request) { static int __launch_request_do(request_h request) { if (request->loader_id == PAD_LOADER_ID_DIRECT || request->cpc == nullptr || - __asan_app_checker.CheckAsanApp(request->menu_info->appid)) { + launchpad::Debug::GetInst().CheckAsanApp(request->menu_info->appid)) { __fork_processing(request); return 0; } @@ -3368,6 +3267,8 @@ static int __before_loop(int argc, char** argv) { launchpad::LauncherInfoInflator inflator; launcher_info_list = inflator.Inflate(LAUNCHER_INFO_PATH); + launchpad::Debug::GetInst().Init(); + __add_app_defined_loaders(); ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL); @@ -3400,7 +3301,7 @@ static void __after_loop(void) { if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0) _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL); - _debug_fini(); + launchpad::Debug::GetInst().Dispose(); launcher_info_list.clear(); _config_fini(); _inotify_fini(); diff --git a/src/launchpad-process-pool/launchpad_debug.cc b/src/launchpad-process-pool/launchpad_debug.cc deleted file mode 100644 index d94c194..0000000 --- a/src/launchpad-process-pool/launchpad_debug.cc +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Copyright (c) 2016 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_debug.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "launchpad-process-pool/debugger_info.hh" -#include "lib/common/inc/key.h" -#include "lib/common/inc/launchpad_common.h" -#include "lib/common/inc/launchpad_types.h" - -#define DEBUGGER_INFO_PATH "/usr/share/aul" - -namespace { - -int __debug_initialized; -std::vector __debugger_info_list; -launchpad::DebuggerInfoPtr __debugger_info; -std::vector __debug_argv_list; -std::vector __extra_argv_list; - -} // namespace - -int _debug_change_mount_namespace(void) { - const char* pid_str; - char buf[PATH_MAX]; - int ret; - int fd; - - pid_str = getenv("TARGET_PID"); - if (pid_str == nullptr) - return 0; - - snprintf(buf, sizeof(buf), "/proc/%s/ns/mnt", pid_str); - fd = open(buf, O_RDONLY); - if (fd < 0) { - _E("open() is failed. path(%s), errno(%d)", buf, errno); - return -1; - } - - ret = setns(fd, CLONE_NEWNS); - close(fd); - if (ret != 0) - _E("setns() is failed. errno(%d)", errno); - - return ret; -} - -int _debug_create_extra_argv(int* argc, char*** argv) { - int new_argc; - char** new_argv; - int i; - - if (argc == nullptr || argv == nullptr) { - _E("[DEBUG] Invalid parameter"); - return -1; - } - - if (__debugger_info == nullptr) - return 0; - - new_argc = __extra_argv_list.size(); - if (new_argc == 0) - return 0; - - new_argv = static_cast(calloc(new_argc, sizeof(char*))); - if (new_argv == nullptr) { - _E("out of memory"); - return -1; - } - - i = LOADER_ARG_PATH; - for (auto& argv : __extra_argv_list) { - new_argv[i++] = strdup(argv.c_str()); - } - - *argc = new_argc; - *argv = new_argv; - _D("[DEBUG] argc: %d, i: %d", *argc, i); - - return 0; -} - -int _debug_create_argv(int* argc, char*** argv, bool* attach) { - int new_argc = 0; - char** new_argv; - const char* exe; - const char* attach_str; - int i; - - if (argc == nullptr || argv == nullptr || attach == nullptr) { - _E("[DEBUG] Invalid parameter"); - return -1; - } - - if (__debugger_info == nullptr) - return 0; - - exe = __debugger_info->GetExe().data(); - if (exe == nullptr) - return 0; - - attach_str = __debugger_info->GetAttachInfo().c_str(); - if (attach_str && strcasecmp(attach_str, "true") == 0) { - *attach = true; - new_argc++; - } - - auto list = __debugger_info->GetDefaultOptList(); - new_argc += __debug_argv_list.size() + list.size() + 1; - new_argv = static_cast(calloc(new_argc, sizeof(char*))); - if (new_argv == nullptr) { - _E("out of memory"); - return -1; - } - - i = LOADER_ARG_PATH; - new_argv[i++] = strdup(exe); - - for (auto& debug_argv : list) { - new_argv[i++] = strdup(debug_argv.c_str()); - } - - for (auto& debug_argv : __debug_argv_list) { - new_argv[i++] = strdup(debug_argv.c_str()); - } - - *argc = new_argc; - *argv = new_argv; - _D("[DEBUG] argc: %d, argv[0]: %s", new_argc, new_argv[LOADER_ARG_PATH]); - - return 0; -} - -void _debug_destroy_argv(int argc, char** argv) { - int i; - - if (argv == nullptr) - return; - - for (i = 0; i < argc; i++) - free(argv[i]); - free(argv); -} - -int _debug_get_caller_pid(bundle* kb) { - const char* pid_str; - int pid; - - pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID); - if (pid_str == nullptr) - pid_str = bundle_get_val(kb, AUL_K_CALLER_PID); - - if (pid_str == nullptr) - return -1; - - pid = atoi(pid_str); - if (pid <= 1) - return -1; - - return pid; -} - -static int __redirect_std_fds(bundle* kb) { - char path[PATH_MAX]; - char err_buf[1024]; - int fd; - int caller_pid; - - if (kb == nullptr) { - _E("[DEBUG] Invalid parameter"); - return -1; - } - - caller_pid = _debug_get_caller_pid(kb); - if (caller_pid < 0) { - _E("[DEBUG] Failed to get caller pid"); - return -1; - } - - /* stdin */ - snprintf(path, sizeof(path), "/proc/%d/fd/0", caller_pid); - fd = open(path, O_RDONLY); - if (fd < 0) { - _E("[DEBUG] Failed to open %s [%s]", path, - strerror_r(errno, err_buf, sizeof(err_buf))); - return -1; - } - dup2(fd, 0); - close(fd); - - /* stdout */ - snprintf(path, sizeof(path), "/proc/%d/fd/1", caller_pid); - fd = open(path, O_WRONLY); - if (fd < 0) { - _E("[DEBUG] Failed to open %s [%s]", path, - strerror_r(errno, err_buf, sizeof(err_buf))); - return -1; - } - dup2(fd, 1); - close(fd); - - /* stderr */ - snprintf(path, sizeof(path), "/proc/%d/fd/2", caller_pid); - fd = open(path, O_WRONLY); - if (fd < 0) { - _E("[DEBUG] Failed to open %s [%s]", path, - strerror_r(errno, err_buf, sizeof(err_buf))); - return -1; - } - dup2(fd, 2); - close(fd); - - return 0; -} - -static void __add_extra_argv(const std::string& key, bundle* kb) { - const char* str; - const char** str_arr = nullptr; - int len = 0; - int i; - - _D("[DEBUG] key: %s", key.c_str()); - if (bundle_get_type(kb, key.c_str()) & BUNDLE_TYPE_ARRAY) { - str_arr = bundle_get_str_array(kb, key.c_str(), &len); - } else { - str = bundle_get_val(kb, key.c_str()); - if (str) { - str_arr = &str; - len = 1; - } - } - - for (i = 0; i < len; i++) { - if (str_arr[i] == nullptr) - break; - - __extra_argv_list.push_back(str_arr[i]); - } - - if (str_arr) - bundle_del(kb, key.c_str()); -} - -static void __add_debug_argv(const std::string& key, bundle* kb) { - const char* str; - const char** str_arr = nullptr; - int len = 0; - int i; - - _D("[DEBUG] key: %s", key.c_str()); - if (bundle_get_type(kb, key.c_str()) & BUNDLE_TYPE_ARRAY) { - str_arr = bundle_get_str_array(kb, key.c_str(), &len); - } else { - str = bundle_get_val(kb, key.c_str()); - if (str) { - str_arr = &str; - len = 1; - } - } - - for (i = 0; i < len; i++) { - if (str_arr[i] == nullptr) - break; - - __debug_argv_list.push_back(str_arr[i]); - if (!strcmp(key.c_str(), "__DLP_ATTACH_ARG__")) { - if (isdigit(str_arr[i][0])) { - _D("Target PID: %s", str_arr[i]); - setenv("TARGET_PID", str_arr[i], 1); - } - } - } - - if (str_arr) - bundle_del(kb, key.c_str()); -} - -static void __set_debug_env(const std::string& key, bundle* kb) { - const char* str; - const char** str_arr = nullptr; - int len = 0; - int i; - char buf[LINE_MAX] = { - 0, - }; - - _D("[DEBUG] key: %s", key.c_str()); - if (bundle_get_type(kb, key.c_str()) & BUNDLE_TYPE_ARRAY) { - str_arr = bundle_get_str_array(kb, key.c_str(), &len); - } else { - str = bundle_get_val(kb, key.c_str()); - if (str) { - str_arr = &str; - len = 1; - } - } - - if (str_arr == nullptr) - return; - - strncat(buf, str_arr[0], sizeof(buf) - strlen(buf) - 1); - for (i = 1; i < len; i++) { - if (str_arr[i] == nullptr) - break; - - strncat(buf, ",", sizeof(buf) - strlen(buf) - 1); - strncat(buf, str_arr[i], sizeof(buf) - strlen(buf) - 1); - } - - bundle_del(kb, key.c_str()); - _D("[DEBUG] name: %s, value: %s", key.c_str(), buf); - setenv(key.c_str(), buf, 1); -} - -static void __remove_file(const std::string& file) { - _D("[DEBUG] file: %s", file.c_str()); - if (access(file.c_str(), F_OK) == 0) { - if (remove(file.c_str()) != 0) - _W("[DEBUG] Failed to remove %s", file.c_str()); - } -} - -void _debug_prepare_debugger(bundle* kb) { - const char* debugger; - int ret; - - if (kb == nullptr) - return; - - debugger = bundle_get_val(kb, AUL_K_SDK); - if (debugger == nullptr) - return; - - if (!strcmp(debugger, "ASAN")) - setenv("TIZEN_ASAN_ACTIVATION", "1", 1); - - ret = __redirect_std_fds(kb); - if (ret < 0) - _E("[DEBUG] Failed to redirect standard fds"); - - _D("[DEBUG] debugger: %s", debugger); - auto it = - std::find_if(__debugger_info_list.begin(), __debugger_info_list.end(), - [&](const launchpad::DebuggerInfoPtr& info) -> bool { - return strcasecmp(info->GetExe().c_str(), debugger) == 0; - }); - if (it == __debugger_info_list.end()) - return; - - __debugger_info = *it; - for (auto& unlink_file : __debugger_info->GetUnlinkList()) { - __remove_file(unlink_file); - } - - for (auto& extra_env : __debugger_info->GetExtraEnvList()) { - __set_debug_env(extra_env, kb); - } - - for (auto& extra_key : __debugger_info->GetExtraKeyList()) { - __add_debug_argv(extra_key, kb); - } - - for (auto& last_extra_key : __debugger_info->GetLastExtraKeyList()) { - __add_extra_argv(last_extra_key, kb); - } -} - -int _debug_init(void) { - if (__debug_initialized) - return 0; - - launchpad::DebuggerInfoInflator inflator; - __debugger_info_list = inflator.Inflate(DEBUGGER_INFO_PATH); - if (__debugger_info_list.empty()) - return -1; - - __debug_initialized = 1; - - return 0; -} - -void _debug_fini(void) { - if (!__debug_initialized) - return; - - __debugger_info_list.clear(); -} diff --git a/src/launchpad-process-pool/launchpad_debug.h b/src/launchpad-process-pool/launchpad_debug.h deleted file mode 100644 index 7411ba1..0000000 --- a/src/launchpad-process-pool/launchpad_debug.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2016 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_DEBUG_H__ -#define __LAUNCHPAD_DEBUG_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int _debug_change_mount_namespace(void); -int _debug_create_extra_argv(int *arg, char ***argv); -int _debug_create_argv(int *argc, char ***argv, bool *attach); -void _debug_destroy_argv(int argc, char **argv); -int _debug_get_caller_pid(bundle *kb); -void _debug_prepare_debugger(bundle *kb); -int _debug_init(void); -void _debug_fini(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __LAUNCHPAD_DEBUG_H__ */ diff --git a/src/launchpad-process-pool/util.cc b/src/launchpad-process-pool/util.cc index 172d1bd..99fd9da 100644 --- a/src/launchpad-process-pool/util.cc +++ b/src/launchpad-process-pool/util.cc @@ -14,22 +14,30 @@ * limitations under the License. */ -#include "util.hh" +#include "launchpad-process-pool/util.hh" +#include +#include #include +#include namespace launchpad { std::vector Split(const std::string& str, - const std::string& delim) { + const std::string& delim) { const std::regex deli("[^" + delim + "]+"); std::vector result; for (auto i = std::sregex_iterator(str.begin(), str.end(), deli); - i != std::sregex_iterator(); ++i) { + i != std::sregex_iterator(); ++i) result.push_back((*i).str()); - } return result; } +std::string ToUpper(std::string str) { + std::string result = std::move(str); + std::transform(result.begin(), result.end(), result.begin(), ::toupper); + return result; +} + } // namespace launchpad diff --git a/src/launchpad-process-pool/util.hh b/src/launchpad-process-pool/util.hh index 3fffdf0..b0f50e9 100644 --- a/src/launchpad-process-pool/util.hh +++ b/src/launchpad-process-pool/util.hh @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef UTIL_HH_ -#define UTIL_HH_ +#ifndef LAUNCHPAD_PROCESS_POOL_UTIL_HH_ +#define LAUNCHPAD_PROCESS_POOL_UTIL_HH_ #include #include @@ -33,8 +33,10 @@ bool operator==(E a, int x) { } std::vector Split(const std::string& str, - const std::string& delim); + const std::string& delim); + +std::string ToUpper(std::string str); } // namespace launchpad -#endif // UTIL_HH_ +#endif // LAUNCHPAD_PROCESS_POOL_UTIL_HH_ diff --git a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc index 10086da..61279ef 100644 --- a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc +++ b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc @@ -130,9 +130,9 @@ class LaunchpadTest : public ::testing::Test { TEST_F(LaunchpadTest, DebuggerInfoTest) { DebuggerInfoInflator inflator; - auto list = inflator.Inflate("."); - EXPECT_EQ(list.size(), 1); - auto info = std::move(list.front()); + auto map = inflator.Inflate("."); + EXPECT_EQ(map.size(), 1); + auto info = std::move(map["DEBUG"]); EXPECT_EQ(info->GetName(), "DEBUG"); EXPECT_EQ(info->GetExe(), "test_debugger"); EXPECT_EQ(info->GetAppTypes().size(), 2); -- 2.7.4 From cf20e6da0c3050064617eb80f23ed001a101d032 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 27 Mar 2023 05:53:06 +0000 Subject: [PATCH 11/16] Fix child process deadlock issue When a child process accesses the destructor of std::condition_variable, it can potentially go to the deadlock state. To avoid the deadlock issue of the child process, the launchpad allocates the condition variables using new keyword. Change-Id: Icc5709671cb9a54557fc6a78ccb9f416c2e3d114 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/dbus.cc | 11 +++++++---- src/launchpad-process-pool/worker.cc | 6 ++++-- src/launchpad-process-pool/worker.hh | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/launchpad-process-pool/dbus.cc b/src/launchpad-process-pool/dbus.cc index 5fcd93a..3cf6571 100644 --- a/src/launchpad-process-pool/dbus.cc +++ b/src/launchpad-process-pool/dbus.cc @@ -97,20 +97,22 @@ class DBusManager { return; if (getpid() == pid_) { - queue_.Push(std::make_shared(true)); + queue_->Push(std::make_shared(true)); thread_.join(); if (conn_ != nullptr) { g_object_unref(conn_); conn_ = nullptr; } + + delete queue_; } disposed_ = true; } void Send(std::shared_ptr message) { - queue_.Push(std::move(message)); + queue_->Push(std::move(message)); } private: @@ -122,6 +124,7 @@ class DBusManager { return; thread_ = std::thread([&]() -> void { WorkerThread(); }); + queue_ = new tizen_base::SharedQueue>(); disposed_ = false; } @@ -177,7 +180,7 @@ class DBusManager { continue; } - auto message = queue_.WaitAndPop(); + auto message = queue_->WaitAndPop(); if (message->IsDone()) break; @@ -192,7 +195,7 @@ class DBusManager { GDBusConnection* conn_ = nullptr; uint32_t error_count_ = 0; std::thread thread_; - tizen_base::SharedQueue> queue_; + tizen_base::SharedQueue>* queue_; }; } // namespace diff --git a/src/launchpad-process-pool/worker.cc b/src/launchpad-process-pool/worker.cc index 28e3596..9b261b4 100644 --- a/src/launchpad-process-pool/worker.cc +++ b/src/launchpad-process-pool/worker.cc @@ -39,17 +39,19 @@ class Ender : public Worker::Job { Worker::Worker(std::string name) : name_(std::move(name)) { thread_ = std::thread([&]() -> void { RunThread(); }); + queue_ = new tizen_base::SharedQueue>(); } Worker::~Worker() { if (getpid() == current_pid) { Add(std::make_shared()); thread_.join(); + delete queue_; } } void Worker::Add(std::shared_ptrjob) { - queue_.Push(std::move(job)); + queue_->Push(std::move(job)); } void Worker::SetComm() { @@ -69,7 +71,7 @@ void Worker::RunThread() { _W("BEGIN"); SetComm(); while (true) { - auto job = queue_.WaitAndPop(); + auto job = queue_->WaitAndPop(); job->Do(); if (job->IsDone()) break; diff --git a/src/launchpad-process-pool/worker.hh b/src/launchpad-process-pool/worker.hh index ed12083..32afdaf 100644 --- a/src/launchpad-process-pool/worker.hh +++ b/src/launchpad-process-pool/worker.hh @@ -47,7 +47,7 @@ class Worker { private: std::string name_; std::thread thread_; - tizen_base::SharedQueue> queue_; + tizen_base::SharedQueue>* queue_; }; } // namespace launchpad -- 2.7.4 From 009d9aee0c67f7ce22f0f453579307677f018b15 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Mon, 27 Mar 2023 14:43:29 +0900 Subject: [PATCH 12/16] Add create_directories() exception handling std::filesystem::create_directories() can throw an exception. This patch adds the exception handling for the above case. Change-Id: I37228b7b38ae1c9894ae2b1586429c39e8379e63 Signed-off-by: Changgyu Choi --- src/launchpad-process-pool/file_monitor.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/launchpad-process-pool/file_monitor.cc b/src/launchpad-process-pool/file_monitor.cc index 01d0e1f..27c9d80 100644 --- a/src/launchpad-process-pool/file_monitor.cc +++ b/src/launchpad-process-pool/file_monitor.cc @@ -55,8 +55,15 @@ FileMonitor::FileMonitor(const std::string_view file_path, parent_path_ = path.parent_path(); file_name_ = path.filename(); if (!fs::exists(parent_path_)) { - if (!fs::create_directories(parent_path_)) { - _E("Failed to create directory. %s", parent_path_.c_str()); + try { + if (!fs::create_directories(parent_path_)) { + _E("Failed to create directory. %s", parent_path_.c_str()); + disposed_ = true; + return; + } + } catch (const std::exception& e) { + _E("Exception has been occurred: %s", e.what()); + disposed_ = true; return; } } -- 2.7.4 From 3b53078bbd27bae82b08b2a1bf0b6cd12dd8d34b Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Mon, 27 Mar 2023 15:19:49 +0900 Subject: [PATCH 13/16] Release version 0.26.2 Changes: - Add CPUChecker and AppInfo classes - Refactor launchpad debug - Fix child process deadlock issue - Add create_directories() exception handling Change-Id: Ib477dc3da9a3a5462696255cacb2562c90a25433 Signed-off-by: Changgyu Choi --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 624d67f..434b497 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.26.1 +Version: 0.26.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 4f32cd8393ec0c771e57f4e4295137a9dd677dbb Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 24 Mar 2023 06:42:10 +0000 Subject: [PATCH 14/16] Refactor launchpad config The launchpad config is implemented using C++ language. Change-Id: I0b4e01abed0e8b07fc2763b79362312177064959 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/config.cc | 167 ++++++++++++++ src/launchpad-process-pool/config.hh | 106 +++++++++ src/launchpad-process-pool/launchpad.cc | 67 ++---- src/launchpad-process-pool/launchpad_config.cc | 303 ------------------------- src/launchpad-process-pool/launchpad_config.h | 48 ---- src/launchpad-process-pool/log.cc | 6 +- src/launchpad-process-pool/logger.cc | 6 +- src/launchpad-process-pool/memory_monitor.cc | 7 +- src/lib/launchpad-common/CMakeLists.txt | 1 + src/lib/launchpad-common/ini_parser.cc | 43 ++++ src/lib/launchpad-common/ini_parser.hh | 42 ++++ 11 files changed, 392 insertions(+), 404 deletions(-) create mode 100644 src/launchpad-process-pool/config.cc create mode 100644 src/launchpad-process-pool/config.hh delete mode 100644 src/launchpad-process-pool/launchpad_config.cc delete mode 100644 src/launchpad-process-pool/launchpad_config.h create mode 100644 src/lib/launchpad-common/ini_parser.cc create mode 100644 src/lib/launchpad-common/ini_parser.hh diff --git a/src/launchpad-process-pool/config.cc b/src/launchpad-process-pool/config.cc new file mode 100644 index 0000000..1d5b2a0 --- /dev/null +++ b/src/launchpad-process-pool/config.cc @@ -0,0 +1,167 @@ +/* + * 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/config.hh" + +#include + +#include "launchpad-process-pool/log_private.hh" + +namespace launchpad { +namespace { + +constexpr const char kPathLaunchpadConf[] = "/usr/share/aul/launchpad.conf"; + +constexpr const char kTagMemoryStatus[] = "MemoryStatus"; +constexpr const char kKeyMemoryStatusLowKey[] = "LowKey"; +constexpr const char kKeyMemoryStatusLowValue[] = "LowValue"; +constexpr const char kKeyMemoryStatusNormalKey[] = "NormalKey"; +constexpr const char kKeyMemoryStatusNormalValue[] = "NormalValue"; + +constexpr const char kTagMemoryMonitor[] = "MemoryMonitor"; +constexpr const char kKeyMemoryMonitorThreshold[] = "Threshold"; +constexpr const char kKeyMemoryMonitorInterval[] = "Interval"; + +constexpr const char kTagCpuChecker[] = "CpuChecker"; +constexpr const char kKeyCpuCheckerMaxCount[] = "MaxCount"; + +constexpr const char kTagLogger[] = "Logger"; +constexpr const char kKeyLoggerPath[] = "Path"; +constexpr const char kKeyLoggerEnable[] = "Enable"; + +} // namespace + +const std::string& Config::MemoryStatus::GetLowKey() const { + return low_key_; +} + +const int Config::MemoryStatus::GetLowValue() const { + return low_value_; +} + +const std::string& Config::MemoryStatus::GetNormalKey() const { + return normal_key_; +} + +const int Config::MemoryStatus::GetNormalValue() const { + return normal_value_; +} + +Config::MemoryStatus::MemoryStatus(const IniParser& parser) { + auto low_key = parser.Get(kTagMemoryStatus, kKeyMemoryStatusLowKey); + if (!low_key.empty()) + low_key_ = std::move(low_key); + + auto low_value = parser.Get(kTagMemoryStatus, kKeyMemoryStatusLowValue); + if (!low_value.empty() && std::isdigit(low_value[0])) + low_value_ = std::stoi(low_value); + + auto normal_key = parser.Get(kTagMemoryStatus, kKeyMemoryStatusNormalKey); + if (!normal_key.empty()) + normal_key_ = std::move(normal_key); + + auto normal_value = parser.Get(kTagMemoryStatus, + kKeyMemoryStatusNormalValue); + if (!normal_value.empty() && std::isdigit(normal_value[0])) + normal_value_ = std::stoi(normal_value); + + _W("[MemoryStatus] Low: %s:%d, Normal: %s:%d", + low_key_.c_str(), low_value_, normal_key_.c_str(), normal_value_); +} + +const int Config::MemoryMonitor::GetThreshold() const { + return threshold_; +} + +const int Config::MemoryMonitor::GetInterval() const { + return interval_; +} + +Config::MemoryMonitor::MemoryMonitor(const IniParser& parser) { + auto threshold = parser.Get(kTagMemoryMonitor, kKeyMemoryMonitorThreshold); + if (!threshold.empty() && std::isdigit(threshold[0])) + threshold_ = std::stoi(threshold); + + auto interval = parser.Get(kTagMemoryMonitor, kKeyMemoryMonitorInterval); + if (!interval.empty() && std::isdigit(interval[0])) + interval_ = std::stoi(interval); + + _W("[MemoryMonitor] thrshold: %d, interval: %d", threshold_, interval_); +} + +const int Config::CPUChecker::GetMaxCount() const { + return max_count_; +} + +Config::CPUChecker::CPUChecker(const IniParser& parser) { + auto max_count = parser.Get(kTagCpuChecker, kKeyCpuCheckerMaxCount); + if (!max_count.empty() && std::isdigit(max_count[0])) + max_count_ = std::stoi(max_count); + + _W("[CPUChecker] max_count: %d", max_count_); +} + +const std::string& Config::Logger::GetPath() const { + return path_; +} + +const bool Config::Logger::IsEnabled() const { + return enable_; +} + +Config::Logger::Logger(const IniParser& parser) { + auto path = parser.Get(kTagLogger, kKeyLoggerPath); + if (!path.empty()) + path_ = std::move(path); + + auto enable = parser.Get(kTagLogger, kKeyLoggerEnable); + if (!enable.empty() && std::isdigit(enable[0])) + enable_ = std::stoi(enable) ? true : false; + + _W("[Logger] path: %s, enable: %s", + path_.c_str(), enable_ ? "true" : "false"); +} + +Config& Config::GetInst() { + static Config inst; + return inst; +} + +Config::Config() + : parser_(IniParser(kPathLaunchpadConf)), + memory_status_(Config::MemoryStatus(parser_)), + memory_monitor_(Config::MemoryMonitor(parser_)), + cpu_checker_(Config::CPUChecker(parser_)), + logger_(Config::Logger(parser_)) { +} + +const Config::MemoryStatus& Config::GetMemoryStatus() const { + return memory_status_; +} + +const Config::MemoryMonitor& Config::GetMemoryMonitor() const { + return memory_monitor_; +} + +const Config::CPUChecker& Config::GetCPUChecker() const { + return cpu_checker_; +} + +const Config::Logger& Config::GetLogger() const { + return logger_; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/config.hh b/src/launchpad-process-pool/config.hh new file mode 100644 index 0000000..4a5f1f6 --- /dev/null +++ b/src/launchpad-process-pool/config.hh @@ -0,0 +1,106 @@ +/* + * 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_CONFIG_HH_ +#define LAUNCHPAD_PROCESS_POOL_CONFIG_HH_ + +#include + +#include + +#include + +namespace launchpad { + +class Config { + public: + class MemoryStatus { + public: + explicit MemoryStatus(const IniParser& parser); + + const std::string& GetLowKey() const; + const int GetLowValue() const; + const std::string& GetNormalKey() const; + const int GetNormalValue() const; + + private: + std::string low_key_ = VCONFKEY_SYSMAN_LOW_MEMORY; + int low_value_ = VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING; + std::string normal_key_ = VCONFKEY_SYSMAN_LOW_MEMORY; + int normal_value_ = VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL; + }; + + class MemoryMonitor { + public: + explicit MemoryMonitor(const IniParser& parser); + + const int GetThreshold() const; + const int GetInterval() const; + + private: + int threshold_ = 80; + int interval_ = 5000; + }; + + class CPUChecker { + public: + explicit CPUChecker(const IniParser& parser); + + const int GetMaxCount() const; + + private: + int max_count_ = 10; + }; + + class Logger { + public: + explicit Logger(const IniParser& parser); + + const std::string& GetPath() const; + const bool IsEnabled() const; + + private: + std::string path_ = "/var/log/appfw"; + bool enable_ = false; + }; + + Config(const Config&) = delete; + Config& operator = (const Config&) = delete; + Config(Config&&) = delete; + Config& operator = (Config&&) = delete; + + static Config& GetInst(); + + const MemoryStatus& GetMemoryStatus() const; + const MemoryMonitor& GetMemoryMonitor() const; + const CPUChecker& GetCPUChecker() const; + const Logger& GetLogger() const; + + private: + Config(); + ~Config() = default; + + private: + IniParser parser_; + MemoryStatus memory_status_; + MemoryMonitor memory_monitor_; + CPUChecker cpu_checker_; + Logger logger_; +}; + +} // namespace launchpad + +#endif // LAUNCHPAD_PROCESS_POOL_CONFIG_HH_ diff --git a/src/launchpad-process-pool/launchpad.cc b/src/launchpad-process-pool/launchpad.cc index 1acda44..e814ef4 100644 --- a/src/launchpad-process-pool/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -44,7 +44,6 @@ #include #include "launchpad-process-pool/launcher_info.hh" -#include "launchpad-process-pool/launchpad_config.h" #include "launchpad-process-pool/launchpad_inotify.h" #include "launchpad-process-pool/launchpad_io_channel.h" #include "launchpad-process-pool/slot_info.h" @@ -54,6 +53,7 @@ #include "lib/common/inc/launchpad_types.h" #include "lib/common/inc/perf.h" +#include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/debug.hh" #include "launchpad-process-pool/dbus.hh" #include "launchpad-process-pool/loader_info.hh" @@ -269,10 +269,6 @@ GHashTable* __pid_table; int __memory_status_low; int __memory_status_normal; sequencer __sequencer; -int MEMORY_STATUS_LOW; -int MEMORY_STATUS_NORMAL; -int MAX_CPU_CHECK_COUNT; - io_channel_h __logger_channel; io_channel_h __label_monitor_channel; io_channel_h __launchpad_channel; @@ -1700,7 +1696,8 @@ static gboolean __handle_idle_checker(gpointer data) { __update_threshold(cpc, 0.05f); cpc->cpu_check_count++; - if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) { + if (cpc->cpu_check_count == + launchpad::Config::GetInst().GetCPUChecker().GetMaxCount()) { _W("CPU check count has exceeded %d times. loader(%s:%d)", cpc->cpu_check_count, cpc->loader_name, cpc->type); __sequencer.idle_checker = 0; @@ -2950,7 +2947,9 @@ static bool __is_low_memory(void) { if (MemoryManager::GetInst().IsLowMemory()) return true; - if (__memory_status_low >= MEMORY_STATUS_LOW) + + if (__memory_status_low >= + launchpad::Config::GetInst().GetMemoryStatus().GetLowValue()) return true; return false; @@ -2990,7 +2989,8 @@ static void __memory_status_low_changed_cb(keynode_t* node, void* data) { GList* iter; __memory_status_low = vconf_keynode_get_int(node); - if (__memory_status_low >= MEMORY_STATUS_LOW) { + if (__memory_status_low >= + launchpad::Config::GetInst().GetMemoryStatus().GetLowValue()) { _W("Low memory"); iter = candidate_slot_list; while (iter) { @@ -3006,7 +3006,8 @@ static void __memory_status_normal_changed_cb(keynode_t* node, void* data) { GList* iter; __memory_status_normal = vconf_keynode_get_int(node); - if (__memory_status_normal == MEMORY_STATUS_NORMAL) { + if (__memory_status_normal == + launchpad::Config::GetInst().GetMemoryStatus().GetNormalValue()) { _W("Normal"); iter = candidate_slot_list; while (iter) { @@ -3018,17 +3019,11 @@ static void __memory_status_normal_changed_cb(keynode_t* node, void* data) { } static void __unregister_vconf_events(void) { - const char* key; - config_type_e type; - - type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY; - key = _config_get_string_value(type); - vconf_ignore_key_changed(key, __memory_status_normal_changed_cb); - - type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY; - key = _config_get_string_value(type); - vconf_ignore_key_changed(key, __memory_status_low_changed_cb); - + auto& config = launchpad::Config::GetInst(); + vconf_ignore_key_changed(config.GetMemoryStatus().GetNormalKey().c_str(), + __memory_status_normal_changed_cb); + vconf_ignore_key_changed(config.GetMemoryStatus().GetLowKey().c_str(), + __memory_status_low_changed_cb); vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, __region_format_changed_cb); vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang); vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, @@ -3039,8 +3034,6 @@ static int __register_vconf_events(void) { int r; char* lang; char* region; - const char* key; - config_type_e type; r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &__sys_hwacc); if (r != VCONF_OK) @@ -3073,29 +3066,24 @@ static int __register_vconf_events(void) { if (r != VCONF_OK) _E("Failed to register callback for regionformat. err = %d", r); - type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY; - key = _config_get_string_value(type); - type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE; - MEMORY_STATUS_LOW = _config_get_int_value(type); - - r = vconf_get_int(key, &__memory_status_low); + auto& config = launchpad::Config::GetInst(); + r = vconf_get_int(config.GetMemoryStatus().GetLowKey().c_str(), + &__memory_status_low); if (r != VCONF_OK) _E("Failed to get vconf low memory. err = %d", r); - r = vconf_notify_key_changed(key, __memory_status_low_changed_cb, nullptr); + r = vconf_notify_key_changed(config.GetMemoryStatus().GetLowKey().c_str(), + __memory_status_low_changed_cb, nullptr); if (r != 0) _E("Failed to register callback for low memory. err = %d", r); - type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY; - key = _config_get_string_value(type); - type = CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE; - MEMORY_STATUS_NORMAL = _config_get_int_value(type); - - r = vconf_get_int(key, &__memory_status_normal); + r = vconf_get_int(config.GetMemoryStatus().GetNormalKey().c_str(), + &__memory_status_normal); if (r != VCONF_OK) _E("Failed to get vconf normal memory. err = %d", r); - r = vconf_notify_key_changed(key, __memory_status_normal_changed_cb, nullptr); + r = vconf_notify_key_changed(config.GetMemoryStatus().GetNormalKey().c_str(), + __memory_status_normal_changed_cb, nullptr); if (r != 0) _E("Failed to register callback for normal memory. err = %d", r); @@ -3253,15 +3241,9 @@ static int __before_loop(int argc, char** argv) { if (ret != 0) _W("Failed to initialize label monitor"); - ret = _config_init(); - if (ret != 0) - _W("Failed to initialize config"); _inotify_init(); MemoryManager::GetInst().Init(); - - MAX_CPU_CHECK_COUNT = - _config_get_int_value(CONFIG_TYPE_CPU_CHECKER_MAX_COUNT); __add_default_slots(); launchpad::LauncherInfoInflator inflator; @@ -3303,7 +3285,6 @@ static void __after_loop(void) { launchpad::Debug::GetInst().Dispose(); launcher_info_list.clear(); - _config_fini(); _inotify_fini(); app_defined_loader_info_manager->Dispose(); diff --git a/src/launchpad-process-pool/launchpad_config.cc b/src/launchpad-process-pool/launchpad_config.cc deleted file mode 100644 index 434973d..0000000 --- a/src/launchpad-process-pool/launchpad_config.cc +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 2019 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_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lib/common/inc/launchpad_common.h" - -#define PATH_LAUNCHPAD_CONF "/usr/share/aul/launchpad.conf" -#define TAG_MEMORY_STATUS "MemoryStatus" -#define KEY_MEMORY_STATUS_LOW_KEY "LowKey" -#define KEY_MEMORY_STATUS_LOW_VALUE "LowValue" -#define KEY_MEMORY_STATUS_NORMAL_KEY "NormalKey" -#define KEY_MEMORY_STATUS_NORMAL_VALUE "NormalValue" - -#define TAG_MEMORY_MONITOR "MemoryMonitor" -#define KEY_MEMORY_MONITOR_THRESHOLD "Threshold" -#define KEY_MEMORY_MONITOR_INTERVAL "Interval" - -#define TAG_CPU_CHECKER "CpuChecker" -#define KEY_CPU_CHECKER_MAX_COUNT "MaxCount" - -#define TAG_LOGGER "Logger" -#define KEY_LOGGER_PATH "Path" -#define KEY_LOGGER_ENABLE "Enable" - -struct memory_status_s { - char* low_key; - int low_value; - char* normal_key; - int normal_value; -}; - -struct memory_monitor_s { - int threshold; - int interval; -}; - -struct cpu_checker_s { - int max_count; -}; - -struct logger_s { - char* path; - int enable; -}; - -static struct memory_status_s __memory_status; -static struct memory_monitor_s __memory_monitor; -static struct cpu_checker_s __cpu_checker; -static struct logger_s __logger; - -const char* _config_get_string_value(config_type_e type) { - const char* value; - - switch (type) { - case CONFIG_TYPE_MEMORY_STATUS_LOW_KEY: - value = __memory_status.low_key; - break; - case CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY: - value = __memory_status.normal_key; - break; - case CONFIG_TYPE_LOGGER_PATH: - value = __logger.path; - break; - default: - _E("Unknown type"); - value = NULL; - break; - } - - return value; -} - -int _config_get_int_value(config_type_e type) { - int value; - - switch (type) { - case CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE: - value = __memory_status.low_value; - break; - case CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE: - value = __memory_status.normal_value; - break; - case CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD: - value = __memory_monitor.threshold; - break; - case CONFIG_TYPE_MEMORY_MONITOR_INTERVAL: - value = __memory_monitor.interval; - break; - case CONFIG_TYPE_CPU_CHECKER_MAX_COUNT: - value = __cpu_checker.max_count; - break; - case CONFIG_TYPE_LOGGER_ENABLE: - value = __logger.enable; - break; - default: - _E("Unknown type"); - value = INT_MIN; - } - - return value; -} - -static const char* __get_string_value(dictionary* d, - const char* tag, - const char* key) { - char buf[128]; - - snprintf(buf, sizeof(buf), "%s:%s", tag, key); - return iniparser_getstring(d, buf, NULL); -} - -static int __get_int_value(dictionary* d, const char* tag, const char* key) { - char buf[128]; - - snprintf(buf, sizeof(buf), "%s:%s", tag, key); - return iniparser_getint(d, buf, INT_MIN); -} - -static void __memory_status_init(void) { - __memory_status.low_key = strdup(VCONFKEY_SYSMAN_LOW_MEMORY); - __memory_status.low_value = VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING; - __memory_status.normal_key = strdup(VCONFKEY_SYSMAN_LOW_MEMORY); - __memory_status.normal_value = VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL; -} - -static void __memory_status_fini(void) { - __memory_status.normal_value = 0; - free(__memory_status.normal_key); - __memory_status.low_value = 0; - free(__memory_status.low_key); -} - -static void __memory_status_set(dictionary* d) { - const char* str; - char* val; - int ret; - - str = __get_string_value(d, TAG_MEMORY_STATUS, KEY_MEMORY_STATUS_LOW_KEY); - if (str) { - val = strdup(str); - if (val) { - free(__memory_status.low_key); - __memory_status.low_key = val; - } - } - - ret = __get_int_value(d, TAG_MEMORY_STATUS, KEY_MEMORY_STATUS_LOW_VALUE); - if (ret != INT_MIN) - __memory_status.low_value = ret; - - str = __get_string_value(d, TAG_MEMORY_STATUS, KEY_MEMORY_STATUS_NORMAL_KEY); - if (str) { - val = strdup(str); - if (val) { - free(__memory_status.normal_key); - __memory_status.normal_key = val; - } - } - - ret = __get_int_value(d, TAG_MEMORY_STATUS, KEY_MEMORY_STATUS_NORMAL_VALUE); - if (ret != INT_MIN) - __memory_status.normal_value = ret; - - _W("Memory Status Low(%s:%d), Normal(%s:%d)", __memory_status.low_key, - __memory_status.low_value, __memory_status.normal_key, - __memory_status.normal_value); -} - -static void __memory_monitor_init(void) { - __memory_monitor.threshold = 80; /* 80 % */ - __memory_monitor.interval = 5000; /* 5 seconds */ -} - -static void __memory_monitor_fini(void) { - __memory_monitor.threshold = 0; - __memory_monitor.interval = 0; -} - -static void __memory_monitor_set(dictionary* d) { - int ret; - - ret = __get_int_value(d, TAG_MEMORY_MONITOR, KEY_MEMORY_MONITOR_THRESHOLD); - if (ret != INT_MIN) - __memory_monitor.threshold = ret; - - ret = __get_int_value(d, TAG_MEMORY_MONITOR, KEY_MEMORY_MONITOR_INTERVAL); - if (ret != INT_MIN) - __memory_monitor.interval = ret; - - _W("Memory Monitor Threshold(%d), Interval(%d)", __memory_monitor.threshold, - __memory_monitor.interval); -} - -static void __cpu_checker_init(void) { - __cpu_checker.max_count = 10; -} - -static void __cpu_checker_fini(void) { - __cpu_checker.max_count = 0; -} - -static void __cpu_checker_set(dictionary* d) { - int ret; - - ret = __get_int_value(d, TAG_CPU_CHECKER, KEY_CPU_CHECKER_MAX_COUNT); - if (ret != INT_MIN) - __cpu_checker.max_count = ret; - - _W("CPU Checker MaxCount(%d)", __cpu_checker.max_count); -} - -static void __logger_init(void) { - __logger.path = strdup("/var/log/appfw"); - __logger.enable = false; -} - -static void __logger_fini(void) { - free(__logger.path); -} - -static void __logger_set(dictionary* d) { - const char* str; - int val; - - str = __get_string_value(d, TAG_LOGGER, KEY_LOGGER_PATH); - if (str) { - free(__logger.path); - __logger.path = strdup(str); - } - _W("Logger path(%s)", __logger.path); - - val = __get_int_value(d, TAG_LOGGER, KEY_LOGGER_ENABLE); - if (val >= 0) - __logger.enable = val; - _W("Logger enable(%d)", __logger.enable); -} - -int _config_init(void) { - dictionary* d; - int ret; - - _D("config init"); - - __memory_status_init(); - __memory_monitor_init(); - __cpu_checker_init(); - __logger_init(); - - ret = access(PATH_LAUNCHPAD_CONF, F_OK); - if (ret != 0) { - _W("The file doesn't exist. errno(%d)", errno); - return 0; - } - - d = iniparser_load(PATH_LAUNCHPAD_CONF); - if (!d) { - _E("Failed to load the config file"); - return -1; - } - - __memory_status_set(d); - __memory_monitor_set(d); - __cpu_checker_set(d); - __logger_set(d); - - iniparser_freedict(d); - - return 0; -} - -void _config_fini(void) { - _D("config fini"); - - __logger_fini(); - __cpu_checker_fini(); - __memory_monitor_fini(); - __memory_status_fini(); -} diff --git a/src/launchpad-process-pool/launchpad_config.h b/src/launchpad-process-pool/launchpad_config.h deleted file mode 100644 index 23fd60b..0000000 --- a/src/launchpad-process-pool/launchpad_config.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 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_CONFIG_H__ -#define __LAUNCHPAD_CONFIG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - CONFIG_TYPE_MEMORY_STATUS_LOW_KEY, - CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE, - CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY, - CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE, - CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD, - CONFIG_TYPE_MEMORY_MONITOR_INTERVAL, - CONFIG_TYPE_CPU_CHECKER_MAX_COUNT, - CONFIG_TYPE_LOGGER_PATH, - CONFIG_TYPE_LOGGER_ENABLE, -} config_type_e; - -const char *_config_get_string_value(config_type_e type); - -int _config_get_int_value(config_type_e type); - -int _config_init(void); - -void _config_fini(void); - -#ifdef __cplusplus -} -#endif - -#endif /* __LAUNCHPAD_CONFIG_H__ */ diff --git a/src/launchpad-process-pool/log.cc b/src/launchpad-process-pool/log.cc index db2da84..8d22e5b 100644 --- a/src/launchpad-process-pool/log.cc +++ b/src/launchpad-process-pool/log.cc @@ -23,8 +23,7 @@ #include -#include "launchpad-process-pool/launchpad_config.h" - +#include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/log_private.hh" #include "launchpad-process-pool/logger.hh" @@ -36,8 +35,7 @@ std::unique_ptr logger_; } // namespace void Log::Init() { - const std::string log_path = - _config_get_string_value(CONFIG_TYPE_LOGGER_PATH) + + const std::string log_path = Config::GetInst().GetLogger().GetPath() + std::string("/launchpad/launchpad.log"); try { logger_.reset(new Logger(log_path)); diff --git a/src/launchpad-process-pool/logger.cc b/src/launchpad-process-pool/logger.cc index 2ac3229..689068c 100644 --- a/src/launchpad-process-pool/logger.cc +++ b/src/launchpad-process-pool/logger.cc @@ -30,7 +30,7 @@ #include -#include "launchpad-process-pool/launchpad_config.h" +#include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/log_private.hh" namespace launchpad { @@ -66,7 +66,7 @@ int CreateDirectory(const std::string &path) { int CreateLaunchpadDirectories() { const std::string logger_path = - _config_get_string_value(CONFIG_TYPE_LOGGER_PATH); + launchpad::Config::GetInst().GetLogger().GetPath(); if (CreateDirectory(logger_path) != 0) return -1; @@ -83,7 +83,7 @@ int CreateLaunchpadDirectories() { } // namespace Logger::Logger(std::string path) : path_(std::move(path)) { - if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) { + if (!launchpad::Config::GetInst().GetLogger().IsEnabled()) { disabled_ = true; return; } diff --git a/src/launchpad-process-pool/memory_monitor.cc b/src/launchpad-process-pool/memory_monitor.cc index 54acde4..ebe809a 100644 --- a/src/launchpad-process-pool/memory_monitor.cc +++ b/src/launchpad-process-pool/memory_monitor.cc @@ -18,7 +18,7 @@ #include -#include "launchpad-process-pool/launchpad_config.h" +#include "launchpad-process-pool/config.hh" #include "launchpad-process-pool/log_private.hh" namespace launchpad { @@ -29,8 +29,9 @@ constexpr const float INTERVAL_BASE_RATE = 0.15f; } // namespace MemoryMonitor::MemoryMonitor(IEvent* listener) : listener_(listener) { - threshold_ = _config_get_int_value(CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD); - base_interval_ = _config_get_int_value(CONFIG_TYPE_MEMORY_MONITOR_INTERVAL); + auto& config = Config::GetInst(); + threshold_ = config.GetMemoryMonitor().GetThreshold(); + base_interval_ = config.GetMemoryMonitor().GetInterval(); interval_ = base_interval_; } diff --git a/src/lib/launchpad-common/CMakeLists.txt b/src/lib/launchpad-common/CMakeLists.txt index 35449e3..3a434d4 100644 --- a/src/lib/launchpad-common/CMakeLists.txt +++ b/src/lib/launchpad-common/CMakeLists.txt @@ -16,6 +16,7 @@ APPLY_PKG_CONFIG(${TARGET_LAUNCHPAD_COMMON} PUBLIC BUNDLE_DEPS DLOG_DEPS GIO_DEPS + INIPARSER_DEPS ) TARGET_LINK_LIBRARIES(${TARGET_LAUNCHPAD_COMMON} PUBLIC "-ldl") diff --git a/src/lib/launchpad-common/ini_parser.cc b/src/lib/launchpad-common/ini_parser.cc new file mode 100644 index 0000000..5969225 --- /dev/null +++ b/src/lib/launchpad-common/ini_parser.cc @@ -0,0 +1,43 @@ +/* + * 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-common/ini_parser.hh" + +namespace launchpad { + +IniParser::IniParser(const std::string& path) + : dict_(iniparser_load(path.c_str())) {} + +IniParser::~IniParser() { + if (dict_ != nullptr) + iniparser_freedict(dict_); +} + +std::string IniParser::Get(const std::string& section, + const std::string& key) const { + if (dict_ == nullptr) + return ""; + + std::string full_key = section + ":" + key; + const char* value = iniparser_getstring(dict_, full_key.c_str(), nullptr); + if (value == nullptr) + return ""; + + return std::string(value); +} + +} // namespace launchpad + diff --git a/src/lib/launchpad-common/ini_parser.hh b/src/lib/launchpad-common/ini_parser.hh new file mode 100644 index 0000000..661e88c --- /dev/null +++ b/src/lib/launchpad-common/ini_parser.hh @@ -0,0 +1,42 @@ +/* + * 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 LIB_LAUNCHPAD_COMMON_INI_PARSER_HH_ +#define LIB_LAUNCHPAD_COMMON_INI_PARSER_HH_ + +#include + +#include + +#undef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) + +namespace launchpad { + +class EXPORT_API IniParser { + public: + explicit IniParser(const std::string& path); + ~IniParser(); + + std::string Get(const std::string& section, const std::string& key) const; + + private: + dictionary* dict_; +}; + +} // namespace launchpad + +#endif // LIB_LAUNCHPAD_COMMON_INI_PARSER_HH_ -- 2.7.4 From 2096cb4f6d764ce86db11d28b19afcb171b81d59 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 29 Mar 2023 09:19:51 +0000 Subject: [PATCH 15/16] Fix wrong socket path The hydra sigchld socket path must be "/run/aul/daemons//.hydra-sigchld-sock". The "/" was missed. This patch fixes it. Change-Id: I13b924a8788fc609e5514153166c4c26174242d1 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/hydra_sigchld_event.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launchpad-process-pool/hydra_sigchld_event.cc b/src/launchpad-process-pool/hydra_sigchld_event.cc index 6f26dd1..b39871a 100644 --- a/src/launchpad-process-pool/hydra_sigchld_event.cc +++ b/src/launchpad-process-pool/hydra_sigchld_event.cc @@ -49,7 +49,7 @@ int CheckPermission(pid_t pid) { HydraSigchldEvent::HydraSigchldEvent(IEvent* listener) : listener_(listener), socket_(new ServerSocket()) { - std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) + + std::string endpoint = "/run/aul/daemons/" + std::to_string(getuid()) + "/" + HYDRA_SIGCHLD_SOCK; socket_->Bind(endpoint); socket_->Listen(MAX_PENDING_CONNECTION); -- 2.7.4 From a46b034d2e775a762d5268a3974e5fc4d627a069 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 29 Mar 2023 09:29:51 +0000 Subject: [PATCH 16/16] Release version 0.26.3 Changes: - Refactor launchpad config - Fix wrong socket path Change-Id: I9d3a2b8d69d091d33d0850acc5b2fe7d343b5a29 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 434b497..93649a3 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.26.2 +Version: 0.26.3 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4