From be806bb06e6891bf88fed19a8ed14024234d5351 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 16 Jan 2023 01:00:42 +0000 Subject: [PATCH 01/16] Wait for threads ready Before calling the security_manager_prepare_app2() function, all threads of the loader process MUST be ready. After this patch is applied, the loader porcess waits until threads are ready if the key-value data related to the thread exists in the extra data. Change-Id: I871b1a53e602dadc50134fca5575a54d6fc1b249 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 15 +++- src/launchpad-loader/conf/default_arch32.loader.in | 3 +- src/launchpad-loader/conf/default_arch64.loader.in | 3 +- src/lib/launchpad/src/launchpad_lib.c | 92 +++++++++++++++++++--- 4 files changed, 101 insertions(+), 12 deletions(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 3fd262b..8ad01c6 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -45,12 +45,18 @@ Obsoletes: amd-mod-launchpad %define tizen_feature_priority_change 0 %define tizen_feature_loader_priority 0 -%ifarch armv7l i586 +%ifarch armv7l i686 i586 %define tizen_arch32 1 %else %define tizen_arch32 0 %endif +%ifarch x86_64 i686 i586 +%define tizen_emulator 1 +%else +%define tizen_emulator 0 +%endif + %if "%{?_prelink_enable}" == "y" %define tizen_feature_prelink 1 %else @@ -125,9 +131,16 @@ _TIZEN_FEATURE_LOADER_ARCH64=ON _TIZEN_FEATURE_PRELINK=ON %endif +%if 0%{?tizen_emulator} +HW_LOADER_THREADS=7 +%else +HW_LOADER_THREADS=8 +%endif + MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake -DVERSION=%{version} \ -DMAJORVER=${MAJORVER} \ + -DHW_LOADER_THREADS=${HW_LOADER_THREADS} \ -D_TIZEN_FEATURE_PRIORITY_CHANGE:BOOL=${_TIZEN_FEATURE_PRIORITY_CHANGE} \ -D_TIZEN_FEATURE_LOADER_PRIORITY:BOOL=${_TIZEN_FEATURE_LOADER_PRIORITY} \ -D_TIZEN_FEATURE_SET_PERSONALITY_32:BOOL=${_TIZEN_FEATURE_SET_PERSONALITY_32} \ diff --git a/src/launchpad-loader/conf/default_arch32.loader.in b/src/launchpad-loader/conf/default_arch32.loader.in index 3e076ce..b663eb7 100644 --- a/src/launchpad-loader/conf/default_arch32.loader.in +++ b/src/launchpad-loader/conf/default_arch32.loader.in @@ -17,6 +17,7 @@ EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libcapi-media-player.so.0 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libcapi-media-camera.so.0 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_evas/engines/extn/@EFL_MODULE_VERSION@/module.so ALTERNATIVE_LOADER common-loader1 +EXTRA threads @HW_LOADER_THREADS@ [LOADER] NAME common-loader1 @@ -31,6 +32,6 @@ EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libappcore-common.so.1 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libcapi-appfw-application.so.0 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_imf/modules/wayland/@EFL_MODULE_VERSION@/module.so EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_evas/engines/extn/@EFL_MODULE_VERSION@/module.so - +EXTRA threads 6 diff --git a/src/launchpad-loader/conf/default_arch64.loader.in b/src/launchpad-loader/conf/default_arch64.loader.in index c1fdc92..bb50a88 100644 --- a/src/launchpad-loader/conf/default_arch64.loader.in +++ b/src/launchpad-loader/conf/default_arch64.loader.in @@ -13,6 +13,7 @@ EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libcapi-appfw-application.so.0 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_imf/modules/wayland/@EFL_MODULE_VERSION@/module.so EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_evas/engines/extn/@EFL_MODULE_VERSION@/module.so ALTERNATIVE_LOADER common-loader1 +EXTRA threads @HW_LOADER_THREADS@ [LOADER] NAME common-loader1 @@ -27,6 +28,6 @@ EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libappcore-common.so.1 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libcapi-appfw-application.so.0 EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_imf/modules/wayland/@EFL_MODULE_VERSION@/module.so EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_evas/engines/extn/@EFL_MODULE_VERSION@/module.so - +EXTRA threads 6 diff --git a/src/lib/launchpad/src/launchpad_lib.c b/src/lib/launchpad/src/launchpad_lib.c index 9bd3832..af20cae 100644 --- a/src/lib/launchpad/src/launchpad_lib.c +++ b/src/lib/launchpad/src/launchpad_lib.c @@ -15,13 +15,18 @@ */ #define _GNU_SOURCE +#include +#include +#include #include #include +#include #include -#include #include -#include -#include +#include +#include +#include + #include #include #include @@ -29,10 +34,6 @@ #include #include -#include -#include -#include - #include "launchpad.h" #include "launchpad_common.h" #include "launchpad_types.h" @@ -355,11 +356,78 @@ static void __region_format_changed_cb(keynode_t *node, void *user_data) setenv("LC_CTYPE", region, 1); } +#ifndef USE_STATUS +static unsigned int __get_thread_count(void) +{ + DIR *dp; + struct dirent *dentry; + unsigned int count = 0; + + dp = opendir("/proc/self/task"); + if (dp == NULL) { + _E("opendir() is failed. errno(%d)", errno); + return 0; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + count++; + } + + closedir(dp); + return count; +} +#else +static unsigned int __get_thread_count(void) +{ + unsigned int count = 0; + char line[LINE_MAX]; + FILE *fp; + + fp = fopen("/proc/self/status", "r"); + if (fp == NULL) { + _E("fopen() is failed"); + return 0; + } + + while (fgets(line, sizeof(line), fp)) { + if (sscanf(line, "Threads: %u", &count) == 1) + break; + } + + fclose(fp); + return count; +} +#endif + +static void __wait_for_threads(unsigned int threads) +{ + unsigned int thread_count; + + if (threads <= 1) + return; + + _W("Thread count = %u", threads); + do { + thread_count = __get_thread_count(); + _D("Current thread count = %u", thread_count); + if (thread_count >= threads) + break; + + usleep(50 * 1000); + } while (threads != thread_count); + _E("Threads(%u) are ready", thread_count); +} + static int __before_loop(int argc, char **argv) { int client_fd; int ret = -1; bundle *extra = NULL; + const char *val; + unsigned int threads = 0; int r; if (_verify_proc_caps() < 0) @@ -382,9 +450,17 @@ static int __before_loop(int argc, char **argv) } if (__loader_callbacks->create) { + val = bundle_get_val(extra, "threads"); + if (val && isdigit(val[0])) { + _D("threads: %s", val); + threads = atoi(val); + } + __loader_callbacks->create(extra, __loader_type, __loader_user_data); ret = 0; + aul_launch_worker_init(); + __wait_for_threads(threads); } if (extra) @@ -409,8 +485,6 @@ static int __before_loop(int argc, char **argv) if (r != VCONF_OK) _E("Failed to register callback for regionformat. error(%d)", r); - aul_launch_worker_init(); - return ret; } -- 2.7.4 From 8250edb891e7e9c7ba67ed4c5e0c0f4c68a91f3b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 16 Jan 2023 05:37:58 +0000 Subject: [PATCH 02/16] Release version 0.22.1 Changes: - Print appid for debugging - Fix build error - Wait for threads ready Change-Id: I0c31efefc993cf2f3916edd1606d9f6e86aea4a5 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 8ad01c6..bd7a843 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.22.0 +Version: 0.22.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 979cea589c8ac2bbf593e3cf1b8d4510921dbc8a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 16 Jan 2023 23:27:29 +0000 Subject: [PATCH 03/16] Add retrying count check for waiting threads If the retyring count is exceeded, the candidate process stops to wait for threads ready. The maximum retrying count is 600. In the worst case, the candidate process can be waitted until 30 seconds. Change-Id: I4c73674c9f783499af1087c3855f56205a52a6ad Signed-off-by: Hwankyu Jhun --- src/lib/launchpad/src/launchpad_lib.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lib/launchpad/src/launchpad_lib.c b/src/lib/launchpad/src/launchpad_lib.c index af20cae..0c7dd27 100644 --- a/src/lib/launchpad/src/launchpad_lib.c +++ b/src/lib/launchpad/src/launchpad_lib.c @@ -404,7 +404,9 @@ static unsigned int __get_thread_count(void) static void __wait_for_threads(unsigned int threads) { +#define MAX_RETRYING_COUNT 600 unsigned int thread_count; + unsigned int retrying_count = 0; if (threads <= 1) return; @@ -412,13 +414,16 @@ static void __wait_for_threads(unsigned int threads) _W("Thread count = %u", threads); do { thread_count = __get_thread_count(); - _D("Current thread count = %u", thread_count); - if (thread_count >= threads) - break; + if (thread_count >= threads) { + _E("Threads(%u) are ready", thread_count); + return; + } + _D("Current thread count = %u", thread_count); usleep(50 * 1000); - } while (threads != thread_count); - _E("Threads(%u) are ready", thread_count); + retrying_count++; + } while (retrying_count < MAX_RETRYING_COUNT); + _E("Maximum retrying count exceeded"); } static int __before_loop(int argc, char **argv) -- 2.7.4 From bee27c1c04f682ab5ca96abaf66157abee2c4eef Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 17 Jan 2023 00:25:59 +0000 Subject: [PATCH 04/16] Release version 0.22.2 Changes: - Add retrying count check for waiting threads Change-Id: Ifb70ace83d91cf386993b37ccca4c97c69182d50 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 bd7a843..0cbc72e 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.22.1 +Version: 0.22.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 4c969c4a6db986fb18a745b613dc0997a1cc95d2 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 19 Jan 2023 01:47:28 +0000 Subject: [PATCH 05/16] Add new APIs for loader process Before calling the loader_launch_cb() callback function, the loader process has to make blocking all sub threads if a new thread is able to be created by the sub thread. This patch adds new functions for the loader process. Some loader process creates a new process while calling the security_manager_prepare_app2(). It makes an application launch failure issue. When calling the loader_prelaunch_cb() callback function, the loader should call the launchpad_loader_block_threads() to make blocking all sub threads. And then, the loader calls the launchpad_loader_unblock_threads() while calling the launchpad_launch_cb() callback function. Even if the sub thread creates a new thread while calling the launchpad_loader_block_threads(), it handles by the security_manager_prepare_app2() function. This is not complete solution. But, this patch is able to reduce the risk about the launch failure issues. Adds: - launchpad_loader_block_threads() - launchpad_loader_unblock_threads() Change-Id: Ib98d435507abbb0d3ebe0a5617d7fcb2509c154e Signed-off-by: Hwankyu Jhun --- src/lib/launchpad/inc/launchpad.h | 21 +++++++ src/lib/launchpad/src/launchpad_lib.c | 111 ++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/src/lib/launchpad/inc/launchpad.h b/src/lib/launchpad/inc/launchpad.h index 86ea976..b7d6c21 100644 --- a/src/lib/launchpad/inc/launchpad.h +++ b/src/lib/launchpad/inc/launchpad.h @@ -81,6 +81,27 @@ int launchpad_loader_set_priority(int prio); bundle *launchpad_loader_get_bundle(void); +/** + * @brief Blocks all sub threads of the loader. + * @remarks This function has to be called in the main thread. + * + * @return @c on success, + * otherwise a negative error value + * + * @see #launchpad_loader_unblock_threads() + */ +int launchpad_loader_block_threads(void); + +/** + * @brief Unblocks all sub threads of the loader. + * @remarks This function has to be called in the main thread. + * + * @return @c on success, + * otherwise a negative error value + * @see #launchpad_loader_block_threads() + */ +int launchpad_loader_unblock_threads(void); + #ifdef __cplusplus } #endif diff --git a/src/lib/launchpad/src/launchpad_lib.c b/src/lib/launchpad/src/launchpad_lib.c index 0c7dd27..7c4512f 100644 --- a/src/lib/launchpad/src/launchpad_lib.c +++ b/src/lib/launchpad/src/launchpad_lib.c @@ -44,6 +44,17 @@ #endif #define AUL_PR_NAME 16 +#define SIGRTINT (SIGRTMIN + 2) + +typedef struct thread_handler_s { + struct sigaction old; + GMutex mutex; + GCond cond; + gint count; + gint num; + bool blocked; + bool done; +} thread_handler_t; static loader_lifecycle_callback_s *__loader_callbacks; static loader_adapter_s *__loader_adapter; @@ -54,6 +65,7 @@ static bundle *__bundle; static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED; static int __loader_id; static bool __loop_quit; +static thread_handler_t __thread_handler; static void __at_exit_to_release_bundle(void) { @@ -580,3 +592,102 @@ API int launchpad_loader_set_priority(int prio) { return _set_priority(prio); } + +static void __signal_handler(int signo) +{ + _D("Block thread"); + g_mutex_lock(&__thread_handler.mutex); + g_atomic_int_set(&__thread_handler.count, + g_atomic_int_get(&__thread_handler.count) - 1); + while (!__thread_handler.done) + g_cond_wait(&__thread_handler.cond, &__thread_handler.mutex); + g_mutex_unlock(&__thread_handler.mutex); + g_atomic_int_inc(&__thread_handler.count); + _D("Unblock thread"); +} + +API int launchpad_loader_block_threads(void) +{ + struct sigaction act; + struct dirent *dentry; + DIR *dp; + pid_t pid = getpid(); + pid_t tid; + gint i; + + if (__thread_handler.blocked) { + _D("Already blocked"); + return 0; + } + + g_mutex_init(&__thread_handler.mutex); + g_cond_init(&__thread_handler.cond); + + memset(&act, '\0', sizeof(act)); + sigemptyset(&act.sa_mask); + act.sa_flags = SA_RESTART; + act.sa_handler = __signal_handler; + + if (sigaction(SIGRTINT, &act, &__thread_handler.old) != 0) { + _E("sigaction() is failed. errno(%d)", errno); + return -1; + } + + __thread_handler.done = false; + __thread_handler.count = 0; + __thread_handler.num = 0; + + dp = opendir("/proc/self/task"); + if (dp == NULL) { + _E("opendir() is failed. errno(%d)", errno); + sigaction(SIGRTINT, &__thread_handler.old, NULL); + return -1; + } + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + tid = atoi(dentry->d_name); + if (tid != pid) { + _D("Send signal to thread(%d)", tid); + if (tgkill(pid, tid, SIGRTINT) != 0) { + _E("tgkill() is failed. errno(%d)", errno); + } else { + g_atomic_int_inc(&__thread_handler.count); + __thread_handler.num++; + } + } + } + closedir(dp); + + for (i = 1000; g_atomic_int_get(&__thread_handler.count) && i; --i) + usleep(2000); + + __thread_handler.blocked = true; + + return 0; +} + +API int launchpad_loader_unblock_threads(void) +{ + gint i; + + if (!__thread_handler.blocked) + return 0; + + g_mutex_lock(&__thread_handler.mutex); + __thread_handler.done = true; + g_cond_broadcast(&__thread_handler.cond); + g_mutex_unlock(&__thread_handler.mutex); + + for (i = 1000; g_atomic_int_get(&__thread_handler.count) != __thread_handler.num && i; --i) + usleep(2000); + + sigaction(SIGRTINT, &__thread_handler.old, NULL); + g_mutex_clear(&__thread_handler.mutex); + g_cond_clear(&__thread_handler.cond); + __thread_handler.blocked = false; + + return 0; +} -- 2.7.4 From 3fe83ade5610d4189122df06b2c29854321f26b4 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 30 Jan 2023 01:33:22 +0000 Subject: [PATCH 06/16] Release version 0.23.0 Changes: - Add new APIs for loader process Change-Id: I8bc1e832f5e1e53a720638eef47111fbad7e06d5 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 0cbc72e..a91fa3c 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.22.2 +Version: 0.23.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 697c543ccc5e2f54e6ca9b6280e12e5b1d30d189 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 31 Jan 2023 06:35:46 +0000 Subject: [PATCH 07/16] Modify loader priority feature After this patch is applied, the loader priority feature is basically activated. The platform developer can adjust a scheduling priority using the loader configuration file. The 'SCEHD_PRIORITY' tag is added for the loader process. The loader developer can set the scheduling priority as below: +------------------------------------------------------------------------------+ | [LOADER] | | NAME hw-loader | | ... | | SCEHD_PRIORITY -20 | +------------------------------------------------------------------------------+ The range of the priority is -20 to 19. (-20 being the highest priority and 19 being the lowest priority.) If the loader has the sched priority tag, the child process sets the scheduling priority using the configure information after the process is created. And then, the loader process sets the priority to the normal priority before running the main loop. Change-Id: I531cc8381936ef4f6c9b8bad1640a0a8714f2777 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 3 --- packaging/launchpad.spec | 5 ----- src/app-defined-loader/src/app-defined-loader.cc | 21 --------------------- src/launchpad-loader/src/launchpad_loader.c | 7 ------- src/launchpad-process-pool/inc/loader_info.h | 1 + src/launchpad-process-pool/inc/slot_info.h | 1 + src/launchpad-process-pool/src/launchpad.c | 16 +++++++++++++--- src/launchpad-process-pool/src/loader_info.c | 9 ++++++++- src/lib/common/src/launchpad_common.c | 10 ++++++---- src/lib/launchpad/src/launchpad_lib.c | 1 + 10 files changed, 30 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fc8276c..1708bfa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,6 @@ PROJECT(launchpad) IF(_TIZEN_FEATURE_PRIORITY_CHANGE) ADD_DEFINITIONS("-DTIZEN_FEATURE_PRIORITY_CHANGE") ENDIF(_TIZEN_FEATURE_PRIORITY_CHANGE) -IF(_TIZEN_FEATURE_LOADER_PRIORITY) - ADD_DEFINITIONS("-DTIZEN_FEATURE_LOADER_PRIORITY") -ENDIF(_TIZEN_FEATURE_LOADER_PRIORITY) IF(_TIZEN_FEATURE_SET_PERSONALITY_32) ADD_DEFINITIONS("-DTIZEN_FEATURE_SET_PERSONALITY_32") ENDIF(_TIZEN_FEATURE_SET_PERSONALITY_32) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index a91fa3c..a48227f 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -44,7 +44,6 @@ Provides: app-launchpad Obsoletes: amd-mod-launchpad %define tizen_feature_priority_change 0 -%define tizen_feature_loader_priority 0 %ifarch armv7l i686 i586 %define tizen_arch32 1 %else @@ -119,9 +118,6 @@ export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE" %if 0%{?tizen_feature_priority_change} _TIZEN_FEATURE_PRIORITY_CHANGE=ON %endif -%if 0%{?tizen_feature_loader_priority} -_TIZEN_FEATURE_LOADER_PRIORITY=ON -%endif %if 0%{?tizen_arch32} _TIZEN_FEATURE_SET_PERSONALITY_32=ON %else @@ -142,7 +138,6 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` -DMAJORVER=${MAJORVER} \ -DHW_LOADER_THREADS=${HW_LOADER_THREADS} \ -D_TIZEN_FEATURE_PRIORITY_CHANGE:BOOL=${_TIZEN_FEATURE_PRIORITY_CHANGE} \ - -D_TIZEN_FEATURE_LOADER_PRIORITY:BOOL=${_TIZEN_FEATURE_LOADER_PRIORITY} \ -D_TIZEN_FEATURE_SET_PERSONALITY_32:BOOL=${_TIZEN_FEATURE_SET_PERSONALITY_32} \ -D_TIZEN_FEATURE_PRELINK:BOOL=${_TIZEN_FEATURE_PRELINK} \ -D_TIZEN_FEATURE_LOADER_ARCH64:BOOL=${_TIZEN_FEATURE_LOADER_ARCH64} \ diff --git a/src/app-defined-loader/src/app-defined-loader.cc b/src/app-defined-loader/src/app-defined-loader.cc index b96e72e..3e9f368 100644 --- a/src/app-defined-loader/src/app-defined-loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -85,14 +85,6 @@ class AppDefinedLoader { return adapter_; } - void SetLoaderPriority(bool enable) { - loader_priority_enabled_ = enable; - } - - bool IsLoaderPriorityEnabled() { - return loader_priority_enabled_; - } - void SetFdHandler(Ecore_Fd_Handler* fd_handler) { fd_handler_ = fd_handler; } @@ -142,9 +134,6 @@ class AppDefinedLoader { return; } - if (loader->IsLoaderPriorityEnabled()) - launchpad_loader_set_priority(19); - loader->PreloadLib(ex); ecore_init(); setenv("AUL_LOADER_INIT", "1", 1); @@ -153,16 +142,12 @@ class AppDefinedLoader { setenv("AUL_HWACC", "none", 1); else if (loader_type == LOADER_TYPE_HW) setenv("AUL_HWACC", "hw", 1); - - if (loader->IsLoaderPriorityEnabled()) - launchpad_loader_set_priority(0); } static int OnLaunch(int argc, char** argv, const char* app_path, const char* appid, const char* pkgid, const char* pkg_type, void* user_data) { _I("on launch"); - AppDefinedLoader* loader = static_cast(user_data); bundle* kb = launchpad_loader_get_bundle(); if (kb == nullptr) return 0; @@ -318,7 +303,6 @@ class AppDefinedLoader { private: std::shared_ptr lifecycle_cb_ = nullptr; std::shared_ptr adapter_ = nullptr; - bool loader_priority_enabled_ = false; loader_receiver_cb receiver_cb_ = nullptr; Ecore_Fd_Handler* fd_handler_ = nullptr; std::unique_ptr proc_; @@ -331,11 +315,6 @@ class AppDefinedLoader { int main(int argc, char** argv) { launchpad::AppDefinedLoader loader(argc, argv); - -#ifdef TIZEN_FEATURE_LOADER_PRIORITY - loader.SetLoaderPriority(true); -#endif - return launchpad_loader_main(argc, argv, loader.GetLifeCycle().get(), loader.GetAdapter().get(), &loader); } diff --git a/src/launchpad-loader/src/launchpad_loader.c b/src/launchpad-loader/src/launchpad_loader.c index f87150b..b815e48 100644 --- a/src/launchpad-loader/src/launchpad_loader.c +++ b/src/launchpad-loader/src/launchpad_loader.c @@ -203,10 +203,6 @@ static void __loader_create_cb(bundle *extra, int type, void *user_data) return; } -#ifdef TIZEN_FEATURE_LOADER_PRIORITY - launchpad_loader_set_priority(19); -#endif - if (!strcmp(LOADER_TYPE_COMMON, ltype)) __type = TYPE_COMMON; else if (!strcmp(LOADER_TYPE_SW, ltype)) @@ -252,9 +248,6 @@ static void __loader_create_cb(bundle *extra, int type, void *user_data) _E("Failed to register callback for %s", VCONFKEY_SETAPPL_APP_HW_ACCELERATION); } -#ifdef TIZEN_FEATURE_LOADER_PRIORITY - launchpad_loader_set_priority(0); -#endif } static loader_convertible __converter_table[MAX_LOADER_TYPE][MAX_ACC_TYPE] = { diff --git a/src/launchpad-process-pool/inc/loader_info.h b/src/launchpad-process-pool/inc/loader_info.h index 79ec242..6d44b1d 100644 --- a/src/launchpad-process-pool/inc/loader_info.h +++ b/src/launchpad-process-pool/inc/loader_info.h @@ -55,6 +55,7 @@ typedef struct _loader_info { bool is_hydra; bool app_check; int on_boot_timeout; + int sched_priority; } loader_info_t; typedef void (*loader_info_foreach_cb)(loader_info_t *info, void *data); diff --git a/src/launchpad-process-pool/inc/slot_info.h b/src/launchpad-process-pool/inc/slot_info.h index 31cbc16..58de327 100644 --- a/src/launchpad-process-pool/inc/slot_info.h +++ b/src/launchpad-process-pool/inc/slot_info.h @@ -38,6 +38,7 @@ typedef struct slot_info_s { bool is_hydra; bool app_check; int on_boot_timeout; + int sched_priority; } slot_info_t; #endif /* __SLOT_INFO_H__ */ diff --git a/src/launchpad-process-pool/src/launchpad.c b/src/launchpad-process-pool/src/launchpad.c index be6ab2a..e5ca890 100644 --- a/src/launchpad-process-pool/src/launchpad.c +++ b/src/launchpad-process-pool/src/launchpad.c @@ -131,6 +131,7 @@ typedef struct { int cpu_check_count; int on_boot_timeout; guint on_boot_timer; + int sched_priority; } candidate_process_context_t; typedef struct { @@ -779,7 +780,8 @@ static int __real_send(int clifd, int ret) return 0; } -static int __fork_app_process(int (*child_fn)(void *), void *arg) +static int __fork_app_process(int (*child_fn)(void *), void *arg, + int sched_priority) { int pid; int ret; @@ -791,6 +793,9 @@ static int __fork_app_process(int (*child_fn)(void *), void *arg) } if (pid == 0) { + if (sched_priority != 0) + _set_priority(sched_priority); + _W("security_manager_prepare_app_candidate ++"); ret = security_manager_prepare_app_candidate(); _W("security_manager_prepare_app_candidate --"); @@ -957,7 +962,8 @@ static int __prepare_candidate_process(int type, int loader_id) if (ret < 0) return ret; - info->pid = __fork_app_process(__exec_loader_process, info->argv); + info->pid = __fork_app_process(__exec_loader_process, info->argv, + cpt->sched_priority); if (info->pid == -1) { _E("Failed to create a child process. type: %d", type); __candidate_info_free(info); @@ -1430,7 +1436,7 @@ static int __launch_directly(const char *appid, const char *app_path, int clifd, arg.kb = kb; _print_hwc_log("before calling fork(). %s", appid); - pid = __fork_app_process(__exec_app_process, &arg); + pid = __fork_app_process(__exec_app_process, &arg, 0); if (pid <= 0) _E("failed to fork app process"); @@ -1988,6 +1994,7 @@ static int __dispatch_cmd_add_loader(bundle *kb) slot_info.is_hydra = false; slot_info.app_check = true; slot_info.on_boot_timeout = 0; + slot_info.sched_priority = 0; cpc = __add_slot(&slot_info); free(loader_name); @@ -2047,6 +2054,7 @@ static int __dispatch_cmd_add_app_defined_loader(bundle *kb) slot_info.is_hydra = false; slot_info.app_check = true; slot_info.on_boot_timeout = 0; + slot_info.sched_priority = 0; cpc = __add_slot(&slot_info); bundle_free_encoded_rawdata(&extra); @@ -2735,6 +2743,7 @@ static candidate_process_context_t *__create_slot(slot_info_t *info) cpc->pss = 0; cpc->cpu_check_count = 0; cpc->on_boot_timeout = info->on_boot_timeout; + cpc->sched_priority = info->sched_priority; if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) && __is_low_memory()) @@ -3061,6 +3070,7 @@ static void __add_slot_from_info(gpointer data, gpointer user_data) .is_hydra = info->is_hydra, .app_check = info->app_check, .on_boot_timeout = info->on_boot_timeout, + .sched_priority = info->sched_priority, }; if (!strcmp(info->exe, "null")) { diff --git a/src/launchpad-process-pool/src/loader_info.c b/src/launchpad-process-pool/src/loader_info.c index 3788b90..c43986f 100644 --- a/src/launchpad-process-pool/src/loader_info.c +++ b/src/launchpad-process-pool/src/loader_info.c @@ -44,6 +44,7 @@ #define TAG_HYDRA "HYDRA" #define TAG_APP_CHECK "APP_CHECK" #define TAG_ON_BOOT_TIMEOUT "ON_BOOT_TIMEOUT" +#define TAG_SCHED_PRIORITY "SCHED_PRIORITY" #define VAL_ON "ON" #define VAL_OFF "OFF" @@ -62,7 +63,7 @@ static loader_info_t *__create_loader_info() { loader_info_t *info; - info = malloc(sizeof(loader_info_t)); + info = calloc(1, sizeof(loader_info_t)); if (info == NULL) { _E("Out of memory"); return NULL; @@ -312,6 +313,12 @@ static GList *__parse_file(GList *list, const char *path) cur_info->app_check = false; } else if (strcasecmp(TAG_ON_BOOT_TIMEOUT, tok1) == 0) { cur_info->on_boot_timeout = atoi(tok2); + } else if (strcasecmp(TAG_SCHED_PRIORITY, tok1) == 0) { + cur_info->sched_priority = atoi(tok2); + if (cur_info->sched_priority < -20) + cur_info->sched_priority = -20; + else if (cur_info->sched_priority > 19) + cur_info->sched_priority = 19; } } diff --git a/src/lib/common/src/launchpad_common.c b/src/lib/common/src/launchpad_common.c index d474ebc..f062423 100644 --- a/src/lib/common/src/launchpad_common.c +++ b/src/lib/common/src/launchpad_common.c @@ -1049,15 +1049,17 @@ int _setup_stdio(const char *ident) int _set_priority(int prio) { - int r; + int ret; - r = setpriority(PRIO_PGRP, 0, prio); - if (r < 0) { + ret = setpriority(PRIO_PROCESS, 0, prio); + if (ret != 0) { SECURE_LOGE("Failed to set process(%d) priority(%d) - err(%d)", getpid(), prio, errno); + } else { + SECURE_LOGD("priority(%d)", prio); } - return r; + return ret; } static int __dbus_send_message(DBusMessage *callback(void *), void *user_data, diff --git a/src/lib/launchpad/src/launchpad_lib.c b/src/lib/launchpad/src/launchpad_lib.c index 7c4512f..a96f468 100644 --- a/src/lib/launchpad/src/launchpad_lib.c +++ b/src/lib/launchpad/src/launchpad_lib.c @@ -577,6 +577,7 @@ API int launchpad_loader_main(int argc, char **argv, return -1; } + _set_priority(0); _D("[candidate] ecore main loop begin"); __loader_adapter->loop_begin(__loader_user_data); -- 2.7.4 From ce362d2a16d35005af14e68d9cdd9d962f0d38a4 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 31 Jan 2023 22:54:52 +0000 Subject: [PATCH 08/16] Release version 0.23.1 Changes: - Modify loader priority feature Change-Id: I62b68f788ebd326857aef54ff7c013724c368028 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 a48227f..89341a4 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.23.0 +Version: 0.23.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From c9f05f7b9c1bdd134cf093731dbe645c57ab837f Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 2 Feb 2023 07:30:39 +0000 Subject: [PATCH 09/16] Fix wrong condition of maximum count of cpu checker The return value should be compared with the INT_MIN. Change-Id: I83cca8e386abafaecf925c035e239dba28189347 Signed-off-by: Hwankyu Jhun --- src/launchpad-process-pool/src/launchpad_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launchpad-process-pool/src/launchpad_config.c b/src/launchpad-process-pool/src/launchpad_config.c index 90e4256..b1be6ea 100644 --- a/src/launchpad-process-pool/src/launchpad_config.c +++ b/src/launchpad-process-pool/src/launchpad_config.c @@ -251,7 +251,7 @@ static void __cpu_checker_set(dictionary *d) ret = __get_int_value(d, TAG_CPU_CHECKER, KEY_CPU_CHECKER_MAX_COUNT); - if (ret != INT_MAX) + if (ret != INT_MIN) __cpu_checker.max_count = ret; _W("CPU Checker MaxCount(%d)", __cpu_checker.max_count); -- 2.7.4 From 449ff36a4e9ec1fc82d7557006f20a0d2fbb5eb2 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 2 Feb 2023 07:37:25 +0000 Subject: [PATCH 10/16] Release version 0.23.2 Changes: - Fix wrong condition of maximum count of cpu checker Change-Id: Ia8b71a94e2917161c235dee5f9a84c134fe5dcf2 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 89341a4..070f3d7 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.23.1 +Version: 0.23.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 00c0107f79d35b0f20e4aa3e0759e8aa56f2d5f9 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Wed, 1 Feb 2023 16:05:39 +0900 Subject: [PATCH 11/16] Refactor launchpad to c++ We will refactor launchpad to c++ step by step. Changes: - debugger_info - launcher_info - loader_info Change-Id: I973d98b0669c4b752ba6cf7203f83e8c83085dc0 Signed-off-by: Changgyu Choi --- CMakeLists.txt | 2 +- src/launchpad-process-pool/CMakeLists.txt | 1 + src/launchpad-process-pool/inc/debugger_info.h | 35 - src/launchpad-process-pool/inc/debugger_info.hh | 66 + src/launchpad-process-pool/inc/launcher_info.hh | 56 + src/launchpad-process-pool/inc/launchpad_config.h | 8 + src/launchpad-process-pool/inc/launchpad_debug.h | 9 +- src/launchpad-process-pool/inc/launchpad_inotify.h | 8 + .../inc/launchpad_io_channel.h | 8 + src/launchpad-process-pool/inc/loader_info.h | 74 - src/launchpad-process-pool/inc/loader_info.hh | 153 + src/launchpad-process-pool/inc/util.hh | 40 + src/launchpad-process-pool/src/debugger_info.c | 326 -- src/launchpad-process-pool/src/debugger_info.cc | 180 + src/launchpad-process-pool/src/launcher_info.c | 257 -- src/launchpad-process-pool/src/launcher_info.cc | 145 + src/launchpad-process-pool/src/launchpad.c | 3571 -------------------- src/launchpad-process-pool/src/launchpad.cc | 3451 +++++++++++++++++++ .../{launchpad_config.c => launchpad_config.cc} | 1 - src/launchpad-process-pool/src/launchpad_dbus.c | 299 -- src/launchpad-process-pool/src/launchpad_dbus.cc | 277 ++ src/launchpad-process-pool/src/launchpad_debug.c | 451 --- src/launchpad-process-pool/src/launchpad_debug.cc | 412 +++ src/launchpad-process-pool/src/launchpad_inotify.c | 191 -- .../src/launchpad_inotify.cc | 187 + .../src/launchpad_io_channel.c | 174 - .../src/launchpad_io_channel.cc | 154 + .../src/{launchpad_log.c => launchpad_log.cc} | 66 +- src/launchpad-process-pool/src/launchpad_logger.c | 248 -- src/launchpad-process-pool/src/launchpad_logger.cc | 240 ++ .../src/launchpad_memory_monitor.c | 151 - .../src/launchpad_memory_monitor.cc | 141 + src/launchpad-process-pool/src/launchpad_signal.c | 413 --- src/launchpad-process-pool/src/launchpad_signal.cc | 395 +++ src/launchpad-process-pool/src/launchpad_worker.c | 186 - src/launchpad-process-pool/src/launchpad_worker.cc | 179 + src/launchpad-process-pool/src/loader_info.c | 609 ---- src/launchpad-process-pool/src/loader_info.cc | 452 +++ .../{inc/launcher_info.h => src/util.cc} | 27 +- src/lib/common/inc/launchpad_plugin.h | 8 + 40 files changed, 6617 insertions(+), 7034 deletions(-) delete mode 100644 src/launchpad-process-pool/inc/debugger_info.h create mode 100644 src/launchpad-process-pool/inc/debugger_info.hh create mode 100644 src/launchpad-process-pool/inc/launcher_info.hh delete mode 100644 src/launchpad-process-pool/inc/loader_info.h create mode 100644 src/launchpad-process-pool/inc/loader_info.hh create mode 100644 src/launchpad-process-pool/inc/util.hh delete mode 100644 src/launchpad-process-pool/src/debugger_info.c create mode 100644 src/launchpad-process-pool/src/debugger_info.cc delete mode 100644 src/launchpad-process-pool/src/launcher_info.c create mode 100644 src/launchpad-process-pool/src/launcher_info.cc delete mode 100644 src/launchpad-process-pool/src/launchpad.c create mode 100644 src/launchpad-process-pool/src/launchpad.cc rename src/launchpad-process-pool/src/{launchpad_config.c => launchpad_config.cc} (99%) delete mode 100644 src/launchpad-process-pool/src/launchpad_dbus.c create mode 100644 src/launchpad-process-pool/src/launchpad_dbus.cc delete mode 100644 src/launchpad-process-pool/src/launchpad_debug.c create mode 100644 src/launchpad-process-pool/src/launchpad_debug.cc delete mode 100644 src/launchpad-process-pool/src/launchpad_inotify.c create mode 100644 src/launchpad-process-pool/src/launchpad_inotify.cc delete mode 100644 src/launchpad-process-pool/src/launchpad_io_channel.c create mode 100644 src/launchpad-process-pool/src/launchpad_io_channel.cc rename src/launchpad-process-pool/src/{launchpad_log.c => launchpad_log.cc} (52%) delete mode 100644 src/launchpad-process-pool/src/launchpad_logger.c create mode 100644 src/launchpad-process-pool/src/launchpad_logger.cc delete mode 100644 src/launchpad-process-pool/src/launchpad_memory_monitor.c create mode 100644 src/launchpad-process-pool/src/launchpad_memory_monitor.cc delete mode 100644 src/launchpad-process-pool/src/launchpad_signal.c create mode 100644 src/launchpad-process-pool/src/launchpad_signal.cc delete mode 100644 src/launchpad-process-pool/src/launchpad_worker.c create mode 100644 src/launchpad-process-pool/src/launchpad_worker.cc delete mode 100644 src/launchpad-process-pool/src/loader_info.c create mode 100644 src/launchpad-process-pool/src/loader_info.cc rename src/launchpad-process-pool/{inc/launcher_info.h => src/util.cc} (52%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1708bfa..7c79e5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_FILE_OFFSET_BITS=64") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") SET(CMAKE_C_FLAGS_RELEASE "-O2") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS} -std=c++14") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_C_FLAGS} -std=c++17") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") diff --git a/src/launchpad-process-pool/CMakeLists.txt b/src/launchpad-process-pool/CMakeLists.txt index b0af4fe..3175dac 100644 --- a/src/launchpad-process-pool/CMakeLists.txt +++ b/src/launchpad-process-pool/CMakeLists.txt @@ -2,6 +2,7 @@ AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src LAUNCHPAD_PROCESS_POOL_SRCS) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../lib/common/src LIB_COMMON_SRCS) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/inc) ADD_EXECUTABLE(${TARGET_LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_SRCS} diff --git a/src/launchpad-process-pool/inc/debugger_info.h b/src/launchpad-process-pool/inc/debugger_info.h deleted file mode 100644 index ecaae3a..0000000 --- a/src/launchpad-process-pool/inc/debugger_info.h +++ /dev/null @@ -1,35 +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 __DEBUGGER_INFO_H__ -#define __DEBUGGER_INFO_H__ - -#include - -typedef struct debugger_info_s *debugger_info_h; - -GList *_debugger_info_load(const char *path); -void _debugger_info_unload(GList *info); -debugger_info_h _debugger_info_find(GList *info_list, const char *name); -const char *_debugger_info_get_exe(debugger_info_h info); -GList *_debugger_info_get_extra_key_list(debugger_info_h info); -GList *_debugger_info_get_extra_env_list(debugger_info_h info); -GList *_debugger_info_get_unlink_list(debugger_info_h info); -const char *_debugger_info_get_attach(debugger_info_h info); -GList *_debugger_info_get_last_extra_key_list(debugger_info_h info); -GList *_debugger_info_get_default_opt_list(debugger_info_h info); - -#endif /* __DEBUGGER_INFO_H__ */ diff --git a/src/launchpad-process-pool/inc/debugger_info.hh b/src/launchpad-process-pool/inc/debugger_info.hh new file mode 100644 index 0000000..83a578d --- /dev/null +++ b/src/launchpad-process-pool/inc/debugger_info.hh @@ -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. + */ + +#ifndef DEBUGGER_INFO_HH_ +#define DEBUGGER_INFO_HH_ + +#include +#include +#include +#include +#include + +namespace launchpad { + +class DebuggerInfo { + public: + const std::string& GetName() const; + const std::string& GetExe() const; + const std::vector& GetAppTypes() const; + const std::vector& GetExtraKeyList() const; + const std::vector& GetExtraEnvList() const; + const std::vector& GetUnlinkList() const; + const std::string& GetAttachInfo() const; + const std::vector& GetLastExtraKeyList() const; + const std::vector& GetDefaultOptList() const; + + private: + std::string name_; + std::string exe_; + std::vector app_types_; + std::vector extra_key_list_; + std::vector extra_env_list_; + std::vector unlink_list_; + std::string attach_; + std::vector last_extra_key_list_; + std::vector default_opt_list_; + + friend class DebuggerInfoInflator; +}; + +using DebuggerInfoPtr = std::shared_ptr; + +class DebuggerInfoInflator { + public: + std::vector Inflate(const std::string_view path); + private: + void Parse(std::vector& debugger_info_list, + const std::filesystem::path& path); +}; + +} // namespace launchpad + +#endif // DEBUGGER_INFO_HH_ diff --git a/src/launchpad-process-pool/inc/launcher_info.hh b/src/launchpad-process-pool/inc/launcher_info.hh new file mode 100644 index 0000000..0a7c178 --- /dev/null +++ b/src/launchpad-process-pool/inc/launcher_info.hh @@ -0,0 +1,56 @@ +/* + * 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 LAUNCHER_INFO_HH_ +#define LAUNCHER_INFO_HH_ + +#include +#include +#include +#include +#include + +namespace launchpad { + +class LauncherInfo { + public: + const std::string& GetName() const; + const std::string& GetExe() const; + const std::vector& GetAppTypes() const; + const std::vector& GetExtraArgs() const; + + private: + std::string name_; + std::string exe_; + std::vector app_types_; + std::vector extra_args_; + friend class LauncherInfoInflator; +}; + +using LauncherInfoPtr = std::shared_ptr; + +class LauncherInfoInflator { + public: + std::vector Inflate(const std::string_view path); + + private: + void Parse(std::vector& launcher_info_list, + const std::filesystem::path& path); +}; + +} // namespace launchpad + +#endif /* LAUNCHER_INFO_HH_ */ diff --git a/src/launchpad-process-pool/inc/launchpad_config.h b/src/launchpad-process-pool/inc/launchpad_config.h index 0f769db..23fd60b 100644 --- a/src/launchpad-process-pool/inc/launchpad_config.h +++ b/src/launchpad-process-pool/inc/launchpad_config.h @@ -17,6 +17,10 @@ #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, @@ -37,4 +41,8 @@ int _config_init(void); void _config_fini(void); +#ifdef __cplusplus +} +#endif + #endif /* __LAUNCHPAD_CONFIG_H__ */ diff --git a/src/launchpad-process-pool/inc/launchpad_debug.h b/src/launchpad-process-pool/inc/launchpad_debug.h index 1697900..7411ba1 100644 --- a/src/launchpad-process-pool/inc/launchpad_debug.h +++ b/src/launchpad-process-pool/inc/launchpad_debug.h @@ -20,6 +20,10 @@ #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); @@ -29,5 +33,8 @@ void _debug_prepare_debugger(bundle *kb); int _debug_init(void); void _debug_fini(void); -#endif /* __LAUNCHPAD_DEBUG_H__ */ +#ifdef __cplusplus +} +#endif +#endif /* __LAUNCHPAD_DEBUG_H__ */ diff --git a/src/launchpad-process-pool/inc/launchpad_inotify.h b/src/launchpad-process-pool/inc/launchpad_inotify.h index 4db903e..77d1122 100644 --- a/src/launchpad-process-pool/inc/launchpad_inotify.h +++ b/src/launchpad-process-pool/inc/launchpad_inotify.h @@ -19,6 +19,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct inotify_watch_info_s *inotify_watch_info_h; typedef bool (*inotify_watch_cb)(const char *event_name, uint32_t mask, @@ -32,3 +36,7 @@ void _inotify_rm_watch(inotify_watch_info_h handle); int _inotify_init(void); void _inotify_fini(void); + +#ifdef __cplusplus +} +#endif diff --git a/src/launchpad-process-pool/inc/launchpad_io_channel.h b/src/launchpad-process-pool/inc/launchpad_io_channel.h index b9ae867..25fab13 100644 --- a/src/launchpad-process-pool/inc/launchpad_io_channel.h +++ b/src/launchpad-process-pool/inc/launchpad_io_channel.h @@ -27,6 +27,10 @@ typedef enum { IO_NVAL = 0x20, } io_condition_e; +#ifdef __cplusplus +extern "C" { +#endif + typedef bool (*io_channel_event_cb)(int fd, io_condition_e condition, void *user_data); @@ -38,3 +42,7 @@ io_channel_h _io_channel_create(int fd, io_condition_e condition, void _io_channel_destroy(io_channel_h channel); int _io_channel_set_close_on_destroy(io_channel_h channel, bool do_close); + +#ifdef __cplusplus +} +#endif diff --git a/src/launchpad-process-pool/inc/loader_info.h b/src/launchpad-process-pool/inc/loader_info.h deleted file mode 100644 index 6d44b1d..0000000 --- a/src/launchpad-process-pool/inc/loader_info.h +++ /dev/null @@ -1,74 +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. - */ - -#pragma once - -#include -#include -#include - -#define DEFAULT_CPU_THRESHOLD_MAX 90 -#define DEFAULT_CPU_THRESHOLD_MIN 40 - -enum loader_method_e { - METHOD_TIMEOUT = 0x0001, - METHOD_VISIBILITY = 0x0002, - METHOD_DEMAND = 0x0004, - METHOD_REQUEST = 0x0010, - METHOD_AVAILABLE_MEMORY = 0x0020, - METHOD_TTL = 0x0040, - METHOD_OUT_OF_MEMORY = 0x0100, - METHOD_INSTALL = 0x0200, -}; - -typedef struct _loader_info { - int type; - char *name; - char *exe; - GList *app_types; - int detection_method; - int timeout_val; - char *hw_acc; - GList *alternative_loaders; - bundle *extra; - int cpu_threshold_max; - int cpu_threshold_min; - bool on_boot; - bool global; - bool app_exists; - int activation_method; - int deactivation_method; - unsigned int ttl; - bool is_hydra; - bool app_check; - int on_boot_timeout; - int sched_priority; -} loader_info_t; - -typedef void (*loader_info_foreach_cb)(loader_info_t *info, void *data); - -GList *_loader_info_load_dir(const char *path); -GList *_loader_info_load_file(GList *list, const char *path); -GList *_loader_info_unload(GList *list, const char *loader_name); -void _loader_info_dispose(GList *info); -int _loader_info_find_type(GList *info, const char *app_type, bool hwacc); -int _loader_info_find_type_by_loader_name(GList *info, const char *loader_name); -const char* _loader_info_find_loader_path_by_loader_name(GList *info, const char *loader_name); -loader_info_t* _loader_info_find_loader_by_loader_name(GList *info, const char *loader_name); -int *_loader_get_alternative_types(GList *info, int type, int *len); -int _loader_info_foreach(GList *info, loader_info_foreach_cb callback, - void *data); -bool _loader_info_exist_app_type(loader_info_t *info, const char *app_type); diff --git a/src/launchpad-process-pool/inc/loader_info.hh b/src/launchpad-process-pool/inc/loader_info.hh new file mode 100644 index 0000000..d96e029 --- /dev/null +++ b/src/launchpad-process-pool/inc/loader_info.hh @@ -0,0 +1,153 @@ +/* + * 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 LOADER_INFO_HH_ +#define LOADER_INFO_HH_ + +#include + +#include +#include +#include +#include +#include + +#include "util.hh" + +namespace launchpad { + +constexpr int DefaultCpuThresholdMax = 90; +constexpr int DefaultCpuThresholdMin = 40; + +enum class LoaderType : int { + Unsupported = -1, + User = 1, + Dynamic = 100, + Max +}; + +enum class LoaderMethod : int { + Empty = 0x0000, + Timeout = 0x0001, + Visibility = 0x0002, + Demand = 0x0004, + Request = 0x0010, + AvailableMemory = 0x0020, + Ttl = 0x0040, + OutOfMemory = 0x0100, + Install = 0x0200, +}; + +class LoaderInfo { + public: + LoaderType GetType() const; + const std::string& GetName() const; + const std::string& GetExe() const; + int GetCpuThresholdMax() const; + int GetCpuThresholdMin() const; + unsigned int GetTtl() const; + const std::vector& GetAppTypes() const; + LoaderMethod GetDetectionMethod() const; + LoaderMethod GetActivationMethod() const; + LoaderMethod GetDeactivationMethod() const; + const std::string& GetHwAcc() const; + int GetOnbootTimeout() const; + int GetTimeoutVal() const; + int GetSchedPriority() const; + bool IsAppExists() const; + bool IsOnBoot() const; + bool IsHydraEnabled() const; + bool IsNeededAppCheck() const; + tizen_base::Bundle& GetExtra(); + void SetType(LoaderType type); + void SetAppExists(bool exsits); + + private: + LoaderType type_ = LoaderType::Unsupported; + std::string name_; + std::string exe_; + std::vector app_types_; + LoaderMethod detection_method_ = + LoaderMethod::Timeout | LoaderMethod::Visibility | LoaderMethod::Install; + LoaderMethod activation_method_ = LoaderMethod::Empty; + LoaderMethod deactivation_method_ = LoaderMethod::Empty; + int timeout_val_ = 5000; + std::string hw_acc_; + std::vector alternative_loaders_; + tizen_base::Bundle extra_; + int cpu_threshold_max_ = DefaultCpuThresholdMax; + int cpu_threshold_min_ = DefaultCpuThresholdMin; + bool on_boot_ = true; + bool global_ = false; + bool app_exists_ = false; + unsigned int ttl_ = 600U; /* 10 minute */ + bool is_hydra_ = false; + bool app_check_ = true; + int on_boot_timeout_ = 0; + int sched_priority_ = 0; + + friend class LoaderInfoManager; + friend class LoaderInfoInflator; +}; + +using LoaderInfoPtr = std::shared_ptr; + +class LoaderInfoInflator { + public: + std::vector Inflate(const std::string_view path); + void Parse(std::vector& launcher_info_list, + const std::filesystem::path& path); + + private: + void ParseDetectionMethod(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss); + void ParseActivationMethod(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss); + void ParseDeactivationMethod(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss); + void ParseAppTypes(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss); +}; + +class LoaderInfoManager { + public: + explicit LoaderInfoManager(std::string path); + LoaderInfoManager(const LoaderInfoManager&) = delete; + LoaderInfoManager& operator=(const LoaderInfoManager&) = delete; + + void Load(); + void LoadFile(const std::string_view file); + void Unload(const std::string_view loader_name); + void Dispose(); + LoaderType FindHwType(const std::string_view app_type); + LoaderType FindSwType(const std::string_view app_type); + std::string FindLoaderPath(const std::string_view loader_name); + LoaderInfoPtr FindLoaderInfo(const std::string_view loader_name); + std::vector GetAlternativeTypes(LoaderType type); + const std::vector& GetLoaderInfoList() const; + + private: + std::string path_; + std::vector loader_list_; +}; + +} // namespace launchpad + +#endif // LOADER_INFO_HH_ diff --git a/src/launchpad-process-pool/inc/util.hh b/src/launchpad-process-pool/inc/util.hh new file mode 100644 index 0000000..3fffdf0 --- /dev/null +++ b/src/launchpad-process-pool/inc/util.hh @@ -0,0 +1,40 @@ +/* + * 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 UTIL_HH_ +#define UTIL_HH_ + +#include +#include + +namespace launchpad { + +template +E operator|(E a, E b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +template +bool operator==(E a, int x) { + return static_cast(a) == x; +} + +std::vector Split(const std::string& str, + const std::string& delim); + +} // namespace launchpad + +#endif // UTIL_HH_ diff --git a/src/launchpad-process-pool/src/debugger_info.c b/src/launchpad-process-pool/src/debugger_info.c deleted file mode 100644 index e043e58..0000000 --- a/src/launchpad-process-pool/src/debugger_info.c +++ /dev/null @@ -1,326 +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. - */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -#include "launchpad_common.h" -#include "debugger_info.h" - -#define TAG_DEBUGGER "[DEBUGGER]" -#define TAG_NAME "NAME" -#define TAG_EXE "EXE" -#define TAG_APP_TYPE "APP_TYPE" -#define TAG_EXTRA_KEY "EXTRA_KEY" -#define TAG_EXTRA_ENV "EXTRA_ENV" -#define TAG_UNLINK "UNLINK" -#define TAG_ATTACH "ATTACH" -#define TAG_LAST_EXTRA_KEY "LAST_EXTRA_KEY" -#define TAG_DEFAULT_OPT "DEFAULT_OPT" - -struct debugger_info_s { - char *name; - char *exe; - GList *app_types; - GList *extra_key_list; - GList *extra_env_list; - GList *unlink_list; - char *attach; - GList *last_extra_key_list; - GList *default_opt_list; -}; - -static struct debugger_info_s *__create_debugger_info(void) -{ - struct debugger_info_s *info; - - info = calloc(1, sizeof(struct debugger_info_s)); - if (info == NULL) { - _E("out of memory"); - return NULL; - } - - return info; -} - -static void __destroy_debugger_info(gpointer data) -{ - struct debugger_info_s *info = (struct debugger_info_s *)data; - - if (info == NULL) - return; - - if (info->default_opt_list) - g_list_free_full(info->default_opt_list, free); - if (info->last_extra_key_list) - g_list_free_full(info->last_extra_key_list, free); - if (info->attach) - free(info->attach); - if (info->unlink_list) - g_list_free_full(info->unlink_list, free); - if (info->extra_env_list) - g_list_free_full(info->extra_env_list, free); - if (info->extra_key_list) - g_list_free_full(info->extra_key_list, free); - if (info->app_types) - g_list_free_full(info->app_types, free); - if (info->exe) - free(info->exe); - if (info->name) - free(info->name); - free(info); -} - -static void __parse_app_types(struct debugger_info_s *info, char *line) -{ - char *token; - char *saveptr = NULL; - - token = strtok_r(line, " |\t\r\n", &saveptr); - while (token) { - info->app_types = g_list_append(info->app_types, strdup(token)); - token = strtok_r(NULL, " |\t\r\n", &saveptr); - } -} - -static GList *__parse_file(GList *list, const char *path) -{ - FILE *fp; - char buf[LINE_MAX]; - char *tok1 = NULL; - char *tok2 = NULL; - struct debugger_info_s *info = NULL; - - fp = fopen(path, "rt"); - if (fp == NULL) - return list; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - FREE_AND_NULL(tok1); - FREE_AND_NULL(tok2); - sscanf(buf, "%ms %ms", &tok1, &tok2); - if (tok1 && strcasecmp(TAG_DEBUGGER, tok1) == 0) { - if (info) { - _D("name: %s, exe: %s", info->name, info->exe); - list = g_list_append(list, info); - } - - info = __create_debugger_info(); - if (info == NULL) - break; - - continue; - } - - if (!tok1 || !tok2) - continue; - if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#') - continue; - if (info == NULL) - continue; - - if (strcasecmp(TAG_NAME, tok1) == 0) { - info->name = strdup(tok2); - if (info->name == NULL) { - _E("out of memory"); - __destroy_debugger_info(info); - info = NULL; - break; - } - } else if (strcasecmp(TAG_EXE, tok1) == 0) { - info->exe = strdup(tok2); - if (info->exe == NULL) { - _E("out of memory"); - __destroy_debugger_info(info); - info = NULL; - break; - } - } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) { - __parse_app_types(info, &buf[strlen(tok1)]); - if (info->app_types == NULL) { - _E("app_types is NULL"); - __destroy_debugger_info(info); - info = NULL; - break; - } - } else if (strcasecmp(TAG_EXTRA_KEY, tok1) == 0) { - info->extra_key_list = g_list_append( - info->extra_key_list, strdup(tok2)); - } else if (strcasecmp(TAG_EXTRA_ENV, tok1) == 0) { - info->extra_env_list = g_list_append( - info->extra_env_list, strdup(tok2)); - } else if (strcasecmp(TAG_UNLINK, tok1) == 0) { - info->unlink_list = g_list_append(info->unlink_list, - strdup(tok2)); - } else if (strcasecmp(TAG_ATTACH, tok1) == 0) { - info->attach = strdup(tok2); - if (info->attach == NULL) { - _E("attach is NULL"); - __destroy_debugger_info(info); - info = NULL; - break; - } - } else if (strcasecmp(TAG_LAST_EXTRA_KEY, tok1) == 0) { - info->last_extra_key_list = g_list_append( - info->last_extra_key_list, - strdup(tok2)); - } else if (strcasecmp(TAG_DEFAULT_OPT, tok1) == 0) { - info->default_opt_list = g_list_append( - info->default_opt_list, - strdup(tok2)); - } - } - fclose(fp); - - if (info) { - _D("name: %s, exe: %s", info->name, info->exe); - list = g_list_append(list, info); - } - - if (tok1) - free(tok1); - if (tok2) - free(tok2); - - return list; -} - -GList *_debugger_info_load(const char *path) -{ - DIR *dp; - struct dirent *dentry = NULL; - GList *list = NULL; - char buf[PATH_MAX]; - char *ext; - - if (path == NULL) - return NULL; - - dp = opendir(path); - if (dp == NULL) - return NULL; - - while ((dentry = readdir(dp)) != NULL) { - if (dentry->d_name[0] == '.') - continue; - - ext = strrchr(dentry->d_name, '.'); - if (ext && strcmp(ext, ".debugger") == 0) { - snprintf(buf, sizeof(buf), "%s/%s", - path, dentry->d_name); - list = __parse_file(list, buf); - } - } - closedir(dp); - - return list; -} - -void _debugger_info_unload(GList *info) -{ - if (info == NULL) - return; - - g_list_free_full(info, __destroy_debugger_info); -} - -static int __comp_name(gconstpointer a, gconstpointer b) -{ - struct debugger_info_s *info = (struct debugger_info_s *)a; - - if (info == NULL || info->name == NULL || b == NULL) - return -1; - - if (strcasecmp(info->name, b) == 0) - return 0; - - return -1; -} - -debugger_info_h _debugger_info_find(GList *info_list, const char *name) -{ - GList *list; - - if (info_list == NULL || name == NULL) - return NULL; - - list = g_list_find_custom(info_list, name, __comp_name); - if (list == NULL) - return NULL; - - return (debugger_info_h)list->data; -} - -const char *_debugger_info_get_exe(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->exe; -} - -GList *_debugger_info_get_extra_key_list(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->extra_key_list; -} - -GList *_debugger_info_get_extra_env_list(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->extra_env_list; -} - -GList *_debugger_info_get_unlink_list(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->unlink_list; -} - -const char *_debugger_info_get_attach(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->attach; -} - -GList *_debugger_info_get_last_extra_key_list(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->last_extra_key_list; -} - -GList *_debugger_info_get_default_opt_list(debugger_info_h info) -{ - if (info == NULL) - return NULL; - - return info->default_opt_list; -} diff --git a/src/launchpad-process-pool/src/debugger_info.cc b/src/launchpad-process-pool/src/debugger_info.cc new file mode 100644 index 0000000..8cbeaf7 --- /dev/null +++ b/src/launchpad-process-pool/src/debugger_info.cc @@ -0,0 +1,180 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "debugger_info.hh" +#include "launchpad_common.h" +#include "util.hh" + +namespace launchpad { +namespace { + +constexpr const char kTagDebugger[] = "[DEBUGGER]"; +constexpr const char kTagName[] = "NAME"; +constexpr const char kTagExe[] = "EXE"; +constexpr const char kTagAppType[] = "APP_TYPE"; +constexpr const char kTagExtraKey[] = "EXTRA_KEY"; +constexpr const char kTagExtraEnv[] = "EXTRA_ENV"; +constexpr const char kTagUnlink[] = "UNLINK"; +constexpr const char kTagAttach[] = "ATTACH"; +constexpr const char kTagLastExtraKey[] = "LAST_EXTRA_KEY"; +constexpr const char kTagDefaultOpt[] = "DEFAULT_OPT"; + +} // namespace + +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_; +} + +const std::string& DebuggerInfo::GetExe() const { + return exe_; +} + +const std::vector& DebuggerInfo::GetAppTypes() const { + return app_types_; +} + +const std::vector& DebuggerInfo::GetExtraKeyList() const { + return extra_key_list_; +} + +const std::vector& DebuggerInfo::GetExtraEnvList() const { + return extra_env_list_; +} + +const std::vector& DebuggerInfo::GetUnlinkList() const { + return unlink_list_; +} + +const std::string& DebuggerInfo::GetAttachInfo() const { + return attach_; +} + +const std::vector& DebuggerInfo::GetLastExtraKeyList() const { + return last_extra_key_list_; +} + +const std::vector& DebuggerInfo::GetDefaultOptList() const { + return default_opt_list_; +} + +std::vector DebuggerInfoInflator::Inflate( + const std::string_view path) { + fs::path p(path); + if (fs::is_directory(p) == false) + return {}; + + std::vector result; + for (auto& entry : fs::directory_iterator(p)) { + fs::path file(entry.path()); + if (file.extension() == ".debugger") + Parse(result, file); + } + + return result; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/src/launcher_info.c b/src/launchpad-process-pool/src/launcher_info.c deleted file mode 100644 index 89a7ccd..0000000 --- a/src/launchpad-process-pool/src/launcher_info.c +++ /dev/null @@ -1,257 +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. - */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -#include "launcher_info.h" -#include "launchpad_common.h" - -#define TAG_LAUNCHER "[LAUNCHER]" -#define TAG_NAME "NAME" -#define TAG_EXE "EXE" -#define TAG_APP_TYPE "APP_TYPE" -#define TAG_EXTRA_ARG "EXTRA_ARG" - -struct launcher_info_s { - char *name; - char *exe; - GList *app_types; - GList *extra_args; -}; - -static struct launcher_info_s *__create_launcher_info(void) -{ - struct launcher_info_s *info; - - info = calloc(1, sizeof(struct launcher_info_s)); - if (info == NULL) { - _E("out of memory"); - return NULL; - } - - return info; -} - -static void __destroy_launcher_info(gpointer data) -{ - struct launcher_info_s *info = (struct launcher_info_s *)data; - - if (info == NULL) - return; - - if (info->extra_args) - g_list_free_full(info->extra_args, free); - if (info->app_types) - g_list_free_full(info->app_types, free); - if (info->exe) - free(info->exe); - if (info->name) - free(info->name); - free(info); -} - -static void __parse_app_types(struct launcher_info_s *info, char *line) -{ - char *token; - char *saveptr = NULL; - - token = strtok_r(line, " |\t\r\n", &saveptr); - while (token) { - info->app_types = g_list_append(info->app_types, strdup(token)); - token = strtok_r(NULL, " |\t\r\n", &saveptr); - } -} - -static GList *__parse_file(GList *list, const char *path) -{ - FILE *fp; - char buf[LINE_MAX]; - char *tok1 = NULL; - char *tok2 = NULL; - struct launcher_info_s *info = NULL; - - fp = fopen(path, "rt"); - if (fp == NULL) - return list; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - FREE_AND_NULL(tok1); - FREE_AND_NULL(tok2); - sscanf(buf, "%ms %ms", &tok1, &tok2); - if (tok1 && strcasecmp(TAG_LAUNCHER, tok1) == 0) { - if (info) { - _D("name: %s, exe: %s", info->name, info->exe); - list = g_list_append(list, info); - } - - info = __create_launcher_info(); - if (info == NULL) - break; - - continue; - } - - if (!tok1 || !tok2) - continue; - if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#') - continue; - if (info == NULL) - continue; - - if (strcasecmp(TAG_NAME, tok1) == 0) { - info->name = strdup(tok2); - if (info->name == NULL) { - _E("out of memory"); - __destroy_launcher_info(info); - info = NULL; - break; - } - } else if (strcasecmp(TAG_EXE, tok1) == 0) { - info->exe = strdup(tok2); - if (info->exe == NULL) { - _E("out of memory"); - __destroy_launcher_info(info); - info = NULL; - break; - } - if (access(info->exe, F_OK | X_OK) != 0) { - _E("Failed to access %s", info->exe); - __destroy_launcher_info(info); - info = NULL; - } - } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) { - __parse_app_types(info, &buf[strlen(tok1)]); - if (info->app_types == NULL) { - _E("app_types is NULL"); - __destroy_launcher_info(info); - info = NULL; - break; - } - } else if (strcasecmp(TAG_EXTRA_ARG, tok1) == 0) { - info->extra_args = g_list_append(info->extra_args, - strdup(tok2)); - } - } - fclose(fp); - - if (info) { - _D("name: %s, exe: %s", info->name, info->exe); - list = g_list_append(list, info); - } - - if (tok1) - free(tok1); - if (tok2) - free(tok2); - - return list; -} - -GList *_launcher_info_load(const char *path) -{ - DIR *dp; - struct dirent *dentry = NULL; - GList *list = NULL; - char buf[PATH_MAX]; - char *ext; - - if (path == NULL) - return NULL; - - dp = opendir(path); - if (dp == NULL) - return NULL; - - while ((dentry = readdir(dp)) != NULL) { - if (dentry->d_name[0] == '.') - continue; - - ext = strrchr(dentry->d_name, '.'); - if (ext && strcmp(ext, ".launcher") == 0) { - snprintf(buf, sizeof(buf), "%s/%s", - path, dentry->d_name); - list = __parse_file(list, buf); - } - } - closedir(dp); - - return list; -} - -void _launcher_info_unload(GList *info) -{ - if (info == NULL) - return; - - g_list_free_full(info, __destroy_launcher_info); -} - -static int __comp_str(gconstpointer a, gconstpointer b) -{ - if (a == NULL || b == NULL) - return -1; - - return strcmp(a, b); -} - -static int __comp_app_type(gconstpointer a, gconstpointer b) -{ - struct launcher_info_s *info = (struct launcher_info_s *)a; - - if (info == NULL || info->app_types == NULL || b == NULL) - return -1; - - if (g_list_find_custom(info->app_types, b, __comp_str)) - return 0; - - return -1; -} - -launcher_info_h _launcher_info_find(GList *info_list, const char *app_type) -{ - GList *list; - - if (info_list == NULL || app_type == NULL) - return NULL; - - list = g_list_find_custom(info_list, app_type, __comp_app_type); - if (list == NULL) - return NULL; - - return (launcher_info_h)list->data; -} - -const char *_launcher_info_get_exe(launcher_info_h info) -{ - if (info == NULL) - return NULL; - - return info->exe; -} - -GList *_launcher_info_get_extra_args(launcher_info_h info) -{ - if (info == NULL) - return NULL; - - return info->extra_args; -} diff --git a/src/launchpad-process-pool/src/launcher_info.cc b/src/launchpad-process-pool/src/launcher_info.cc new file mode 100644 index 0000000..7387323 --- /dev/null +++ b/src/launchpad-process-pool/src/launcher_info.cc @@ -0,0 +1,145 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "launcher_info.hh" +#include "launchpad_common.h" +#include "util.hh" + +namespace launchpad { +namespace { + +constexpr const char kTagLauncher[] = "[LAUNCHER]"; +constexpr const char kTagName[] = "NAME"; +constexpr const char kTagExe[] = "EXE"; +constexpr const char kTagAppType[] = "APP_TYPE"; +constexpr const char kTagExtraArg[] = "EXTRA_ARG"; + +} // namespace + +namespace fs = std::filesystem; + +const std::string& LauncherInfo::GetName() const { + return name_; +} + +const std::string& LauncherInfo::GetExe() const { + return exe_; +} + +const std::vector& LauncherInfo::GetAppTypes() const { + return app_types_; +} + +const std::vector& LauncherInfo::GetExtraArgs() const { + return extra_args_; +} + +void LauncherInfoInflator::Parse( + std::vector& launcher_info_list, + const fs::path& path) { + std::ifstream fp; + fp.open(path); + if (fp.fail()) + return; + + LauncherInfoPtr info; + std::string input; + while (std::getline(fp, input)) { + std::istringstream ss(input); + std::string tok1, tok2; + if (!(ss >> tok1)) + continue; + + if (strcasecmp(kTagLauncher, tok1.c_str()) == 0) { + if (info != nullptr) { + _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str()); + launcher_info_list.push_back(std::move(info)); + } + + info = std::make_shared(); + 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) { + info->app_types_.push_back(std::move(token)); + } + } while (std::getline(ss, line)); + } else if (kTagExtraArg == key) { + info->extra_args_.push_back(std::move(tok2)); + } + } + + fp.close(); + if (info) { + _D("name: %s, exe: %s", info->name_.c_str(), info->exe_.c_str()); + launcher_info_list.push_back(std::move(info)); + } +} + +std::vector LauncherInfoInflator::Inflate( + const std::string_view path) { + fs::path p(path); + if (fs::is_directory(p) == false) + return {}; + + std::vector result; + for (auto& entry : fs::directory_iterator(p)) { + fs::path file(entry.path()); + if (file.extension() == ".launcher") { + Parse(result, file); + } + } + + return result; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/src/launchpad.c b/src/launchpad-process-pool/src/launchpad.c deleted file mode 100644 index e5ca890..0000000 --- a/src/launchpad-process-pool/src/launchpad.c +++ /dev/null @@ -1,3571 +0,0 @@ -/* - * Copyright (c) 2015 - 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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "key.h" -#include "launcher_info.h" -#include "launchpad_common.h" -#include "launchpad_config.h" -#include "launchpad_dbus.h" -#include "launchpad_debug.h" -#include "launchpad_inotify.h" -#include "launchpad_io_channel.h" -#include "launchpad_log.h" -#include "launchpad_memory_monitor.h" -#include "launchpad_plugin.h" -#include "launchpad_proc.h" -#include "launchpad_signal.h" -#include "launchpad_types.h" -#include "launchpad_worker.h" -#include "loader_info.h" -#include "perf.h" -#include "slot_info.h" - -#define AUL_PR_NAME 16 -#define EXEC_CANDIDATE_EXPIRED 5 -#define EXEC_CANDIDATE_WAIT 1 -#define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a)) -#define CANDIDATE_NONE 0 -#define HYDRA_NONE 0 -#define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock" -#define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock" -#define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader" -#define LOADER_INFO_PATH "/usr/share/aul" -#define OPT_SHARE_PATH "/opt/share" -#define LOADERS_PATH "loaders" -#define APP_DEFINED_LOADER_INFO_PATH OPT_SHARE_PATH "/" LOADERS_PATH -#define COMMON_LOADER_NAME "common-loader1" - -#define LAUNCHER_INFO_PATH LOADER_INFO_PATH -#define REGULAR_UID_MIN 5000 -#define PAD_ERR_FAILED -1 -#define PAD_ERR_REJECTED -2 -#define PAD_ERR_INVALID_ARGUMENT -3 -#define PAD_ERR_INVALID_PATH -4 -#define CPU_CHECKER_TIMEOUT 1000 -#define PI 3.14159265 -#define WIN_SCORE 100 -#define LOSE_SCORE_RATE 0.7f - -enum candidate_process_state_e { - CANDIDATE_PROCESS_STATE_RUNNING, - CANDIDATE_PROCESS_STATE_PAUSED, -}; - -typedef struct { - int type; - bool prepared; - int pid; /* 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; -} candidate_process_context_t; - -typedef struct { - GPollFD *gpollfd; - int type; - int loader_id; -} loader_context_t; - -typedef struct { - GQueue *queue; - guint timer; - guint idle_checker; - candidate_process_context_t *running_cpc; -} sequencer; - -struct app_launch_arg { - const char *appid; - const char *app_path; - appinfo_t *menu_info; - bundle *kb; -}; - -struct app_arg { - int argc; - char **argv; -}; - -struct app_info { - const char *type; - bool exists; -}; - -struct cleanup_info_s { - char *appid; - int pid; -}; - -typedef struct candidate_info_s { - char **argv; - int argc; - int loader_id; - int type; - pid_t pid; -} candidate_info_t; - -typedef struct request_s { - app_pkt_t *pkt; - appinfo_t *menu_info; - bundle *kb; - candidate_process_context_t *cpc; - candidate_process_context_t *org_cpc; - const char *app_path; - int clifd; - int cmd; - int loader_id; - pid_t caller_pid; - uid_t caller_uid; - pid_t pid; /* result */ -} request_t; - -typedef request_t *request_h; - -typedef int (*request_handler)(request_h request); - -static int __sys_hwacc; -static GList *loader_info_list; -static GList *app_defined_loader_info_list; -static int user_slot_offset; -static GList *candidate_slot_list; -static app_labels_monitor *label_monitor; -static GList *launcher_info_list; -static GHashTable *__pid_table; -static int __memory_status_low; -static int __memory_status_normal; -static sequencer __sequencer; -static int MEMORY_STATUS_LOW; -static int MEMORY_STATUS_NORMAL; -static int MAX_CPU_CHECK_COUNT; - -static io_channel_h __logger_channel; -static io_channel_h __label_monitor_channel; -static io_channel_h __launchpad_channel; -static int __client_fd = -1; -static worker_h __cleaner; - -static candidate_process_context_t *__add_slot(slot_info_t *info); -static int __remove_slot(int type, int loader_id); -static int __add_default_slots(void); -static gboolean __handle_idle_checker(gpointer data); -static int __add_idle_checker(int detection_method, GList *cur); -static void __dispose_candidate_process(candidate_process_context_t *cpc); -static bool __is_low_memory(void); -static void __update_slot_state(candidate_process_context_t *cpc, int method, - bool force); -static void __init_app_defined_loader_monitor(void); -static gboolean __launchpad_recovery_cb(gpointer data); -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; - - if (__sequencer.idle_checker > 0) - return G_SOURCE_CONTINUE; - - if (g_queue_is_empty(__sequencer.queue)) { - __sequencer.timer = 0; - return G_SOURCE_REMOVE; - } - - cpc = (candidate_process_context_t *)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) { - _W("The application is not installed. Type(%d)", cpc->type); - return G_SOURCE_CONTINUE; - } - - if (cpc->timer) { - g_source_remove(cpc->timer); - cpc->timer = 0; - } - - if (cpc->pid != CANDIDATE_NONE) { - _W("The slot(%d) is already running. pid(%d)", - cpc->type, cpc->pid); - return G_SOURCE_CONTINUE; - } - - _get_cpu_idle(&total, &idle); - cpc->cpu_idle_time = idle; - cpc->cpu_total_time = total; - cpc->cpu_check_count = 0; - - __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT, - __handle_idle_checker, cpc); - __sequencer.running_cpc = cpc; - - _W("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type); - - return G_SOURCE_CONTINUE; -} - -static bool __sequencer_slot_is_running(candidate_process_context_t *cpc) -{ - if (__sequencer.running_cpc == cpc) - return true; - - return false; -} - -static bool __sequencer_slot_exist(candidate_process_context_t *cpc) -{ - GList *found; - - found = g_queue_find(__sequencer.queue, cpc); - if (found) - return true; - - return false; -} - -static int __sequencer_add_slot(candidate_process_context_t *cpc) -{ - if (__sequencer_slot_exist(cpc)) { - _W("Already exists"); - return -1; - } - - if (__sequencer_slot_is_running(cpc)) { - _W("slot(%d) is running", cpc->type); - return -1; - } - - g_queue_push_tail(__sequencer.queue, cpc); - - return 0; -} - -static void __sequencer_remove_slot(candidate_process_context_t *cpc) -{ - g_queue_remove(__sequencer.queue, cpc); -} - -static void __sequencer_run(void) -{ - if (__sequencer.timer) - return; - - __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, NULL); - if (!__sequencer.timer) - _E("Failed to add sequencer timer"); -} - -static void __sequencer_stop(void) -{ - if (!__sequencer.timer) - return; - - g_source_remove(__sequencer.timer); - __sequencer.timer = 0; -} - -static bool __sequencer_queue_is_empty(void) -{ - if (g_queue_is_empty(__sequencer.queue)) - return true; - - return false; -} - -static int __sequencer_init(void) -{ - _D("[__SEQUENCER__] Init"); - - __sequencer.queue = g_queue_new(); - if (!__sequencer.queue) { - _E("Out of memory"); - return -1; - } - - return 0; -} - -static void __sequencer_fini(void) -{ - _D("[__SEQUENCER__] Finish"); - - if (__sequencer.idle_checker > 0) - g_source_remove(__sequencer.idle_checker); - - if (__sequencer.timer > 0) - g_source_remove(__sequencer.timer); - - g_queue_free(__sequencer.queue); -} - -static int __make_loader_id(void) -{ - static int id = PAD_LOADER_ID_DYNAMIC_BASE; - - return ++id; -} - -static candidate_process_context_t *__find_slot_from_static_type(int type) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC || - type == LAUNCHPAD_LOADER_TYPE_UNSUPPORTED) - return NULL; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (type == cpc->type) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static candidate_process_context_t *__find_slot_from_pid(int pid) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (pid == cpc->pid) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static candidate_process_context_t *__find_hydra_slot_from_pid(int pid) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (cpc->is_hydra && pid == cpc->hydra_pid) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static candidate_process_context_t *__find_slot_from_caller_pid(int caller_pid) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (caller_pid == cpc->caller_pid) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static candidate_process_context_t *__find_slot_from_loader_id(int id) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (id == cpc->loader_id) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static candidate_process_context_t *__find_slot_from_loader_name(const char *loader_name) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (strcmp(cpc->loader_name, loader_name) == 0) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static candidate_process_context_t *__find_slot(int type, int loader_id) -{ - if (type == LAUNCHPAD_LOADER_TYPE_DYNAMIC) - return __find_slot_from_loader_id(loader_id); - - return __find_slot_from_static_type(type); -} - -static void __update_slot_score(candidate_process_context_t *slot) -{ - if (!slot) - return; - - slot->score *= LOSE_SCORE_RATE; - slot->score += WIN_SCORE; -} - -static void __update_slots_pss(void) -{ - candidate_process_context_t *cpc; - GList *iter; - - iter = candidate_slot_list; - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - iter = g_list_next(iter); - - if (cpc->pid == CANDIDATE_NONE) - continue; - - _proc_get_mem_pss(cpc->pid, &cpc->pss); - } -} - -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; - - if (slot_a->is_hydra && !slot_b->is_hydra) - return -1; - if (!slot_a->is_hydra && slot_b->is_hydra) - return 1; - - if (slot_a->score < slot_b->score) - return 1; - if (slot_a->score > slot_b->score) - return -1; - - if (slot_a->pss < slot_b->pss) - return -1; - if (slot_a->pss > slot_b->pss) - return 1; - - return 0; -} - -static candidate_process_context_t *__get_running_slot(bool is_hydra) -{ - candidate_process_context_t *cpc; - GList *iter; - - iter = candidate_slot_list; - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) - return cpc; - - iter = g_list_next(iter); - } - - return NULL; -} - -static void __pause_all_running_slots(bool is_hydra) -{ - candidate_process_context_t *cpc = NULL; - GList *iter; - - iter = g_list_last(candidate_slot_list); - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) { - __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, true); - if (!_memory_monitor_is_low_memory()) - return; - } - - iter = g_list_previous(iter); - } -} - -static void __resume_all_slots(void) -{ - candidate_process_context_t *cpc; - GList *iter; - - iter = candidate_slot_list; - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true); - - iter = g_list_next(iter); - } -} - -static void __kill_process(int pid) -{ - char err_str[MAX_LOCAL_BUFSZ] = { 0, }; - - if (kill(pid, SIGKILL) == -1) { - _E("send SIGKILL: %s", - strerror_r(errno, err_str, sizeof(err_str))); - } -} - -static void __refuse_candidate_process(int server_fd) -{ - int client_fd = -1; - - if (server_fd == -1) { - _E("arguments error!"); - goto error; - } - - client_fd = accept(server_fd, NULL, NULL); - if (client_fd == -1) { - _E("accept error!"); - goto error; - } - - close(client_fd); - _D("refuse connection!"); - -error: - return; -} - -static int __accept_candidate_process(int server_fd, int *out_client_fd, - int *out_client_pid, int cpc_pid) -{ - int client_fd = -1; - int recv_pid = 0; - int ret; - socklen_t len; - struct ucred cred = {}; - - if (server_fd == -1 || out_client_fd == NULL || - out_client_pid == NULL) { - _E("arguments error!"); - goto error; - } - - client_fd = accept(server_fd, NULL, NULL); - if (client_fd == -1) { - _E("accept error!"); - goto error; - } - - if (_set_sock_option(client_fd, 1) < 0) { - _E("Failed to set sock option"); - goto error; - } - - ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL); - if (ret == -1) { - _E("recv error!"); - goto error; - } - - len = (socklen_t)sizeof(cred); - ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len); - if (ret < 0) { - _E("getsockopt error"); - goto error; - } - - if (cpc_pid != -1 && cred.pid != cpc_pid) { - _E("Invalid accept. pid(%d)", cred.pid); - goto error; - } - - if (cred.pid != recv_pid) - _W("Not equal recv and real pid"); - - *out_client_fd = client_fd; - *out_client_pid = cred.pid; - - return *out_client_fd; - -error: - if (client_fd != -1) - close(client_fd); - - return -1; -} - -static int __listen_addr(struct sockaddr_un *addr) -{ - int fd = -1; - fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (fd < 0) { - _E("Socket error"); - goto error; - } - - unlink(addr->sun_path); - - _D("bind to %s", addr->sun_path); - if (bind(fd, (struct sockaddr *)addr, sizeof(struct sockaddr_un)) < 0) { - _E("bind error"); - goto error; - } - - _D("listen to %s", addr->sun_path); - if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) { - _E("listen error"); - goto error; - } - - SECURE_LOGD("[launchpad] done, listen fd: %d", fd); - return fd; - -error: - if (fd != -1) - close(fd); - - return -1; -} - -static int __listen_candidate_process(int type, int loader_id) -{ - struct sockaddr_un addr; - - _D("[launchpad] enter, type: %d", type); - - 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); - - return __listen_addr(&addr); -} - -static int __listen_hydra_process(int type, int loader_id) -{ - struct sockaddr_un addr; - - _D("[launchpad] enter, type: %d", type); - - 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); - - return __listen_addr(&addr); -} - -static int __get_loader_id(bundle *kb) -{ - const char *val; - - val = bundle_get_val(kb, AUL_K_LOADER_ID); - if (val == NULL) - return -1; - _W("Requested loader id: %s", val); - - return atoi(val); -} - -static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt) -{ - return _send_pkt_raw(candidate_fd, pkt); -} - -static int __real_send(int clifd, int ret) -{ - if (clifd < 3) { - _E("Invalid parameter. clifd(%d)", clifd); - return -1; - } - - if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) { - if (errno == EPIPE) { - _E("send failed due to EPIPE."); - close(clifd); - return -1; - } - _E("send fail to client"); - } - - close(clifd); - return 0; -} - -static int __fork_app_process(int (*child_fn)(void *), void *arg, - int sched_priority) -{ - int pid; - int ret; - - pid = fork(); - if (pid == -1) { - _E("failed to fork child process"); - return -1; - } - - if (pid == 0) { - if (sched_priority != 0) - _set_priority(sched_priority); - - _W("security_manager_prepare_app_candidate ++"); - ret = security_manager_prepare_app_candidate(); - _W("security_manager_prepare_app_candidate --"); - if (ret != SECURITY_MANAGER_SUCCESS) { - _E("failed to prepare app candidate process (%d)", ret); - exit(1); - } - - ret = child_fn(arg); - _E("failed to exec app process (%d)", errno); - exit(ret); - } - - return pid; -} - -static int __exec_loader_process(void *arg) -{ - char **argv = arg; - char err_buf[1024]; - - _signal_unblock_sigchld(); - _close_all_fds(); - _setup_stdio(basename(argv[LOADER_ARG_PATH])); - - 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))); - } else { - _D("Succeeded to prepare candidate_process"); - } - - return -1; -} - -static gboolean __handle_deactivate_event(gpointer user_data) -{ - candidate_process_context_t *cpc; - - cpc = (candidate_process_context_t *)user_data; - __update_slot_state(cpc, METHOD_TTL, false); - _D("Deactivate event: type(%d)", cpc->type); - - return G_SOURCE_REMOVE; -} - -static void __set_live_timer(candidate_process_context_t *cpc) -{ - if (!cpc) - return; - - if (cpc->deactivation_method & METHOD_TTL) { - if (cpc->live_timer == 0) { - cpc->live_timer = g_timeout_add_seconds(cpc->ttl, - __handle_deactivate_event, cpc); - } - } -} - -static int __hydra_send_request(int fd, enum hydra_cmd cmd) -{ - int sent = 0; - int size = (int)sizeof(cmd); - int send_ret = 0; - - while (sent != size) { - send_ret = send(fd, (char *)&cmd + sent, - size - sent, MSG_NOSIGNAL); - if (send_ret == -1) { - _E("send error! (%d)", errno); - return -1; - } - - sent += send_ret; - _D("send(%d: ret: %d) : %d / %d", - fd, send_ret, sent, size); - } - - return 0; -} - -static int __hydra_send_launch_candidate_request(int fd) -{ - SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd); - return __hydra_send_request(fd, LAUNCH_CANDIDATE); -} - -static void __candidate_info_free(candidate_info_t *info) -{ - int i; - - if (info == NULL) - return; - - if (info->argv) { - for (i = 0; i < info->argc; i++) - free(info->argv[i]); - - free(info->argv); - } - - free(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, }; - char argbuf[LOADER_ARG_LEN]; - candidate_info_t *info; - - if (cpt == NULL) - return -EINVAL; - - info = calloc(1, sizeof(candidate_info_t)); - if (info == NULL) { - _E("calloc() is failed"); - return -ENOMEM; - } - - info->argv = calloc(LOADER_ARG_DUMMY + 1, sizeof(char *)); - if (info->argv == NULL) { - _E("calloc() is failed"); - __candidate_info_free(info); - return -ENOMEM; - } - - memset(argbuf, ' ', LOADER_ARG_LEN); - argbuf[LOADER_ARG_LEN - 1] = '\0'; - info->argv[LOADER_ARG_DUMMY] = strdup(argbuf); - - snprintf(loader_id_str, sizeof(loader_id_str), "%d", cpt->loader_id); - snprintf(type_str, sizeof(type_str), "%d", cpt->type); - info->argv[LOADER_ARG_PATH] = strdup(cpt->loader_path); - info->argv[LOADER_ARG_TYPE] = strdup(type_str); - info->argv[LOADER_ARG_ID] = strdup(loader_id_str); - info->argv[LOADER_ARG_HYDRA] = strdup(cpt->is_hydra ? "1" : "0"); - info->argv[LOADER_ARG_EXTRA] = strdup(cpt->loader_extra); - - info->argc = LOADER_ARG_DUMMY + 1; - info->type = cpt->type; - info->loader_id = cpt->loader_id; - - *candidate_info = info; - return 0; -} - -static int __prepare_candidate_process(int type, int loader_id) -{ - candidate_process_context_t *cpt = __find_slot(type, loader_id); - candidate_info_t *info; - int ret; - - if (cpt == NULL) - return -1; - - if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE) - return __hydra_send_launch_candidate_request(cpt->hydra_fd); - - _D("prepare candidate process / type:%d", type); - ret = __candidate_info_create(cpt, &info); - if (ret < 0) - return ret; - - info->pid = __fork_app_process(__exec_loader_process, info->argv, - cpt->sched_priority); - if (info->pid == -1) { - _E("Failed to create a child process. type: %d", type); - __candidate_info_free(info); - return -1; - } - - _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 == NULL) { - _E("Not found slot."); - __candidate_info_free(info); - return -1; - } - - cpt->last_exec_time = time(NULL); - if (cpt->is_hydra) { - cpt->hydra_pid = info->pid; - } else { - cpt->pid = info->pid; - __set_live_timer(cpt); - } - - _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)", - info->pid, cpt->loader_id, cpt->loader_name); - _memory_monitor_reset_timer(); - __candidate_info_free(info); - return 0; -} - -static gboolean __handle_timeout_event(gpointer user_data) -{ - candidate_process_context_t *cpc; - - cpc = (candidate_process_context_t *)user_data; - cpc->timer = 0; - - if (cpc->pid != CANDIDATE_NONE) { - _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid); - return G_SOURCE_REMOVE; - } - - __sequencer_add_slot(cpc); - __sequencer_run(); - return G_SOURCE_REMOVE; -} - -static void __set_timer(candidate_process_context_t *cpc) -{ - if (cpc == NULL || cpc->timer > 0) - return; - - if ((cpc->detection_method & METHOD_TIMEOUT) && - cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) { - cpc->timer = g_timeout_add(cpc->timeout_val, - __handle_timeout_event, cpc); - } -} - -static void __reset_slot(candidate_process_context_t *cpc) -{ - if (cpc == NULL) - return; - - cpc->send_fd = -1; - cpc->prepared = false; - cpc->pid = CANDIDATE_NONE; - cpc->client_channel = NULL; - cpc->timer = 0; - cpc->live_timer = 0; - cpc->on_boot_timer = 0; -} - -static void __dispose_candidate_process(candidate_process_context_t *cpc) -{ - if (!cpc) - return; - - _D("Dispose candidate process %d", cpc->type); - if (cpc->pid > 0) { - _D("kill process %d", cpc->pid); - __kill_process(cpc->pid); - } - if (cpc->live_timer > 0) - g_source_remove(cpc->live_timer); - if (cpc->client_channel) - _io_channel_destroy(cpc->client_channel); - if (cpc->timer > 0) - g_source_remove(cpc->timer); - if (cpc->send_fd > 0) - close(cpc->send_fd); - if (cpc->on_boot_timer > 0) - g_source_remove(cpc->on_boot_timer); - __reset_slot(cpc); -} - -static void __dispose_hydra_process(candidate_process_context_t *cpc) -{ - if (!cpc) - return; - - __dispose_candidate_process(cpc); - - _D("Dispose hydra process %d", cpc->type); - if (cpc->hydra_pid > 0) { - _D("kill process %d", cpc->hydra_pid); - __kill_process(cpc->hydra_pid); - cpc->hydra_pid = HYDRA_NONE; - } - - if (cpc->hydra_fd > 0) { - close(cpc->hydra_fd); - cpc->hydra_fd = -1; - } -} - -static int __send_launchpad_loader(candidate_process_context_t *cpc, - app_pkt_t *pkt, const char *app_path, int clifd) -{ - int pid = -1; - int ret; - - ret = _delete_sock_path(cpc->pid, getuid()); - if (ret != 0) - return -1; - - __candidate_process_real_launch(cpc->send_fd, pkt); - SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s", - cpc->pid, app_path); - - pid = cpc->pid; - cpc->pid = CANDIDATE_NONE; - __dispose_candidate_process(cpc); - __set_timer(cpc); - __update_slot_score(cpc); - - return pid; -} - -static int __normal_fork_exec(int argc, char **argv, const char *app_path) -{ - char *libdir; - char err_buf[1024]; - - _D("start real fork and exec"); - - libdir = _get_libdir(app_path); - if (libdir) { - setenv("LD_LIBRARY_PATH", libdir, 1); - free(libdir); - } - - _close_all_fds(); - - 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))); - return -1; - } - /* never reach*/ - return 0; -} - -static int __create_launcher_argv(int *argc, char ***argv, const char *app_type) -{ - int launcher_argc; - char **launcher_argv; - launcher_info_h launcher_info; - const char *exe; - const char *extra_arg; - GList *extra_args; - GList *iter; - int i; - - launcher_info = _launcher_info_find(launcher_info_list, app_type); - if (launcher_info == NULL) - return 0; - - exe = _launcher_info_get_exe(launcher_info); - if (exe == NULL) { - _E("Failed to get launcher exe"); - return -1; - } - - extra_args = _launcher_info_get_extra_args(launcher_info); - launcher_argc = g_list_length(extra_args) + 1; - launcher_argv = (char **)calloc(launcher_argc, sizeof(char *)); - if (launcher_argv == NULL) { - _E("out of memory"); - return -1; - } - - i = LOADER_ARG_PATH; - launcher_argv[i++] = strdup(exe); - - iter = g_list_first(extra_args); - while (iter) { - extra_arg = (const char *)iter->data; - if (extra_arg) - launcher_argv[i++] = strdup(extra_arg); - - iter = g_list_next(iter); - } - - *argc = launcher_argc; - *argv = launcher_argv; - - - return 0; -} - -static void __destroy_launcher_argv(int argc, char **argv) -{ - int i; - - if (argv == NULL) - return; - - for (i = 0; i < argc; i++) - free(argv[i]); - free(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; - } - - 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; - } - - 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; - } - - 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; - } - - new_argv = (char **)calloc(new_argc + 1, sizeof(char *)); - if (new_argv == NULL) { - _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 = 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; -} - -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) != NULL) - putenv("TIZEN_DEBUGGING_PORT=1"); - - ret = __create_app_argv(&app_argc, &app_argv, app_path, - kb, menu_info->app_type); - if (ret < 0) { - _E("Failed to create app argv"); - exit(-1); - } - - for (i = 0; i < app_argc; i++) - SECURE_LOGD("input argument %d : %s##", i, app_argv[i]); - - PERF("setup argument done"); - __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) -{ - char *file_name; - const char *enabled_light_user; - char process_name[AUL_PR_NAME]; - int ret; - - /* Set new session ID & new process group ID*/ - /* In linux, child can set new session ID without check permission */ - /* TODO : should be add to check permission in the kernel*/ - setsid(); - - ret = _launchpad_plugin_prepare_app(appid, kb); - if (ret < 0) { - _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret); - return PAD_ERR_FAILED; - } - - ret = _enable_external_pkg(kb, menu_info->pkgid, - menu_info->global ? GLOBAL_USER : getuid()); - if (ret < 0) - return PAD_ERR_FAILED; - - if (menu_info->global) - ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER); - else - ret = trust_anchor_launch(menu_info->pkgid, getuid()); - if (ret != TRUST_ANCHOR_ERROR_NONE && - ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) { - _E("trust_anchor_launch() returns %d", ret); - return PAD_ERR_REJECTED; - } - - ret = _mount_res_dir(menu_info->root_path, kb); - if (ret < 0) - return PAD_ERR_FAILED; - - if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) - _debug_change_mount_namespace(); - - /* SET PRIVILEGES*/ - enabled_light_user = bundle_get_val(kb, AUL_K_ENABLED_LIGHT_USER); - _W("security_manager_prepare_app2 ++ %s", appid); - ret = security_manager_prepare_app2(appid, enabled_light_user); - _W("security_manager_prepare_app2 -- %s", appid); - if (ret != SECURITY_MANAGER_SUCCESS) - return PAD_ERR_REJECTED; - - if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) - _setup_stdio(basename(app_path)); - - /* SET DUMPABLE - for coredump*/ - prctl(PR_SET_DUMPABLE, 1); - - /* SET PROCESS NAME*/ - if (app_path == NULL) - return PAD_ERR_INVALID_ARGUMENT; - - file_name = strrchr(app_path, '/'); - if (file_name == NULL) - return PAD_ERR_INVALID_PATH; - - file_name++; - if (*file_name == '\0') - return PAD_ERR_INVALID_PATH; - - memset(process_name, '\0', AUL_PR_NAME); - snprintf(process_name, AUL_PR_NAME, "%s", file_name); - prctl(PR_SET_NAME, process_name); - - /* SET ENVIROMENT*/ - _set_env(menu_info, kb); - - ret = _wait_tep_mount(kb); - if (ret < 0) - return PAD_ERR_FAILED; - - if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) { - ret = _prepare_app_socket(); - if (ret < 0) - return PAD_ERR_FAILED; - - ret = _prepare_id_file(); - if (ret < 0) - return PAD_ERR_FAILED; - } - - _send_cmd_to_amd(APP_STARTUP_SIGNAL); - return 0; -} - -static int __exec_app_process(void *arg) -{ - struct app_launch_arg *launch_arg = arg; - int ret; - - _print_hwc_log("%d|after calling fork(). %s", - getpid(), launch_arg->appid); - 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); - - _signal_unblock_sigchld(); - - _delete_sock_path(getpid(), getuid()); - - PERF("prepare exec - first done"); - ret = __prepare_exec(launch_arg->appid, launch_arg->app_path, - launch_arg->menu_info, launch_arg->kb); - if (ret < 0) - return ret; - - PERF("prepare exec - second done"); - __real_launch(launch_arg->app_path, launch_arg->kb, - launch_arg->menu_info); - - 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) -{ - struct app_launch_arg arg; - int pid; - - arg.appid = appid; - arg.app_path = app_path; - arg.menu_info = menu_info; - arg.kb = kb; - - _print_hwc_log("before calling fork(). %s", appid); - pid = __fork_app_process(__exec_app_process, &arg, 0); - if (pid <= 0) - _E("failed to fork app process"); - - SECURE_LOGD("==> real launch pid : %d %s", pid, app_path); - - return pid; -} - -static int __create_sock_activation(void) -{ - int fds; - char launchpad_process_pool_sock_path[108]; - int i; - - 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); - - 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, 0) > 0) - return i; - } - - _W("There is no socket stream"); - return -1; -} - -static int __get_launchpad_listen_fd(void) -{ - const char *val; - - val = getenv("LAUNCHPAD_LISTEN_FD"); - if (!val) { - _E("Failed to get LAUNCHPAD_LISTEN_FD"); - return -1; - } - - _W("Listen Fd: %s", val); - return atoi(val); -} - -static int __launchpad_pre_init(int argc, char **argv) -{ - int fd; - - /* create launchpad sock */ - fd = __create_sock_activation(); - if (fd >= 0) - return fd; - - fd = __get_launchpad_listen_fd(); - if (fd >= 0) - return fd; - - fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK); - if (fd < 0) { - _E("server sock error %d", fd); - return -1; - } - - return fd; -} - -static bool __handle_loader_client_event(int fd, io_condition_e cond, - void *data) -{ - candidate_process_context_t *cpc = data; - - if (cpc == NULL) - return false; - - if (cond & (IO_HUP | IO_NVAL)) { - SECURE_LOGE("Type %d candidate process was " - "(POLLHUP|POLLNVAL), pid: %d", - cpc->type, cpc->pid); - cpc->pid = CANDIDATE_NONE; - __dispose_candidate_process(cpc); - __prepare_candidate_process(cpc->type, cpc->loader_id); - return false; - } - - return true; - -} - -static bool __handle_hydra_client_event(int fd, io_condition_e cond, - void *data) -{ - candidate_process_context_t *cpc = data; - int recv_pid = -1; - int ret; - - if (cpc == NULL) - return false; - - if (cond & (IO_HUP | IO_NVAL)) { - SECURE_LOGE("Type %d hydra process was " - "(POLLHUP|POLLNVAL), pid: %d", - cpc->type, cpc->hydra_pid); - __dispose_hydra_process(cpc); - __prepare_candidate_process(cpc->type, cpc->loader_id); - return false; - } - - if (cond & IO_IN) { - ret = recv(cpc->hydra_fd, &recv_pid, sizeof(recv_pid), - MSG_WAITALL); - if (ret == -1) { - _E("recv() is failed. errno(%d)", errno); - } else { - _W("candidate process: %d", recv_pid); - if (recv_pid > 1) - cpc->pid = recv_pid; - } - } - - return true; -} - -static bool __handle_loader_event(int fd, io_condition_e cond, void *data) -{ - candidate_process_context_t *cpc = data; - int client_fd; - int client_pid; - int ret; - - if (cpc == NULL) - return false; - - if (!cpc->prepared) { - ret = __accept_candidate_process(fd, &client_fd, &client_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 */ - if (cpc->is_hydra) - cpc->pid = client_pid; - - cpc->prepared = true; - cpc->send_fd = client_fd; - - SECURE_LOGI("Type %d candidate process was connected, " - "pid: %d", cpc->type, cpc->pid); - - _print_hwc_log("Type %d candidate process was connected, " - "pid: %d", cpc->type, cpc->pid); - cpc->client_channel = _io_channel_create(client_fd, - IO_IN | IO_HUP, - __handle_loader_client_event, - cpc); - if (!cpc->client_channel) - close(client_fd); - } - } else { - __refuse_candidate_process(fd); - _E("Refused candidate process connection"); - } - - return true; -} - -static bool __handle_hydra_event(int fd, io_condition_e cond, void *data) -{ - candidate_process_context_t *cpc = data; - int client_fd; - int client_pid; - int ret; - - if (cpc == NULL) - return false; - - if (!cpc->prepared) { - ret = __accept_candidate_process(fd, &client_fd, &client_pid, - cpc->hydra_pid); - if (ret >= 0) { - cpc->hydra_fd = client_fd; - - SECURE_LOGD("Type %d hydra process was connected," - " pid: %d", cpc->type, cpc->hydra_pid); - - cpc->client_channel = _io_channel_create(client_fd, - IO_IN | IO_HUP, - __handle_hydra_client_event, - cpc); - if (!cpc->client_channel) - close(client_fd); - } - } else { - __refuse_candidate_process(fd); - _E("Refused hydra process connection"); - } - - 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 = malloc(sizeof(struct cleanup_info_s)); - if (!info) { - _E("Out of memory"); - return NULL; - } - - info->appid = strdup(appid); - if (!info->appid) { - _E("strdup(%s) is failed", appid); - __destroy_cleanup_info(info); - return NULL; - } - - 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 = 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() --"); - } - - g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid)); - } - - _log_print("[SIGCHLD]", "pid(%7d)", pid); - cpc = __find_slot_from_pid(pid); - if (cpc != NULL) { - cpc->pid = CANDIDATE_NONE; - __dispose_candidate_process(cpc); - __prepare_candidate_process(cpc->type, cpc->loader_id); - } else { - cpc = __find_hydra_slot_from_pid(pid); - if (cpc != NULL) { - cpc->hydra_pid = HYDRA_NONE; - __dispose_hydra_process(cpc); - __prepare_candidate_process(cpc->type, cpc->loader_id); - } - } - - cpc = __find_slot_from_caller_pid(pid); - while (cpc) { - __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id); - cpc = __find_slot_from_caller_pid(pid); - } -} - -static bool __handle_label_monitor(int fd, io_condition_e cond, void *data) -{ - candidate_process_context_t *cpc; - GList *iter = candidate_slot_list; - - if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { - _E("fd(%d), io_condition(%d)", fd, cond); - abort(); - return false; - } - - _D("fd(%d) condition(%d)", fd, cond); - _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond); - security_manager_app_labels_monitor_process(label_monitor); - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (cpc->is_hydra) { - if (cpc->hydra_pid > 0) { - __dispose_hydra_process(cpc); - __prepare_candidate_process(cpc->type, - cpc->loader_id); - } - } else if (cpc->pid > 0) { - __dispose_candidate_process(cpc); - __prepare_candidate_process(cpc->type, cpc->loader_id); - } - - iter = g_list_next(iter); - } - - return true; -} - -static float __interpolator(float input, int cpu_max, int cpu_min) -{ - float ret; - float min = cpu_min / 100.0f; - float max = cpu_max / 100.0f; - - if (input > 1.0f) - input = 1.0f; - if (input < 0.0f) - input = 0.0f; - - ret = cos(input * PI) / 2.0f + 0.5f; - ret *= max - min; - ret += min; - - return ret; -} - -static void __update_threshold(candidate_process_context_t *cpc, float delta) -{ - static float pos = 0.0f; - - pos += delta; - if (pos < 0.0f) - pos = 0.0f; - - 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); -} - -static gboolean __handle_idle_checker(gpointer data) -{ - unsigned long long total = 0; - unsigned long long idle = 0; - int per; - candidate_process_context_t *cpc; - - if (!data) { - _E("Critical error!"); - __sequencer.idle_checker = 0; - __sequencer.running_cpc = NULL; - return G_SOURCE_REMOVE; - } - - cpc = (candidate_process_context_t *)data; - if (cpc->app_check && !cpc->app_exists) { - _W("The application is not installed. loader(%s:%d)", - cpc->loader_name, cpc->type); - __sequencer.idle_checker = 0; - __sequencer.running_cpc = NULL; - return G_SOURCE_REMOVE; - } - - if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) { - _W("Slot state is not running. loader(%s:%d)", - cpc->loader_name, cpc->type); - __sequencer.idle_checker = 0; - __sequencer.running_cpc = NULL; - return G_SOURCE_REMOVE; - } - - if (cpc->pid != CANDIDATE_NONE) { - _W("Slot is already running. %d:%s:%d", - cpc->type, cpc->loader_name, cpc->pid); - __sequencer.idle_checker = 0; - __sequencer.running_cpc = NULL; - return G_SOURCE_REMOVE; - } - - _get_cpu_idle(&total, &idle); - if (total == cpc->cpu_total_time) - total++; - - per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time); - _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type); - - if (per >= cpc->threshold) { - __update_threshold(cpc, -0.02f * (per - cpc->threshold)); - __prepare_candidate_process(cpc->type, cpc->loader_id); - cpc->touched = true; - __sequencer.idle_checker = 0; - __sequencer.running_cpc = NULL; - return G_SOURCE_REMOVE; - } - - cpc->cpu_idle_time = idle; - cpc->cpu_total_time = total; - __update_threshold(cpc, 0.05f); - - 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); - __sequencer.idle_checker = 0; - __sequencer.running_cpc = NULL; - __sequencer_add_slot(cpc); - return G_SOURCE_REMOVE; - } - - return G_SOURCE_CONTINUE; -} - -static gboolean __on_boot_timeout_cb(gpointer user_data) -{ - candidate_process_context_t *context = 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); - } else { - __prepare_candidate_process(context->type, context->loader_id); - context->touched = true; - } - - return G_SOURCE_REMOVE; -} - -static void __add_on_boot_timer(candidate_process_context_t *context) -{ - if (context->on_boot_timer != 0) - return; - - context->on_boot_timer = g_timeout_add(context->on_boot_timeout, - __on_boot_timeout_cb, context); -} - -static int __add_idle_checker(int detection_method, GList *cur) -{ - candidate_process_context_t *cpc; - GList *iter = cur; - - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - if (!cpc->touched && cpc->on_boot && cpc->on_boot_timeout > 0) - __add_on_boot_timer(cpc); - - if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) { - iter = g_list_next(iter); - continue; - } - - if (strcmp("null", cpc->loader_path) == 0) { - iter = g_list_next(iter); - continue; - } - - if (!cpc->touched && !cpc->on_boot) { - iter = g_list_next(iter); - continue; - } - - if (cpc->app_check && !cpc->app_exists) { - iter = g_list_next(iter); - continue; - } - - if (cpc->pid == CANDIDATE_NONE && - (!cpc->touched || - (cpc->detection_method & detection_method))) { - if (cpc->timer > 0) { - g_source_remove(cpc->timer); - cpc->timer = 0; - } - - cpc->cur_event = detection_method; - __sequencer_add_slot(cpc); - __sequencer_run(); - } - - iter = g_list_next(iter); - } - - return -1; -} - -static int __dispatch_cmd_hint(bundle *kb, int detection_method) -{ - _W("cmd hint %d", detection_method); - __add_idle_checker(detection_method, candidate_slot_list); - - return 0; -} - -static int __dispatch_cmd_add_loader(bundle *kb) -{ - const char *add_slot_str = NULL; - const char *caller_pid = NULL; - const char *extra; - int lid, size; - char *loader_name; - candidate_process_context_t *cpc; - slot_info_t slot_info; - - _W("cmd add loader"); - add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH); - caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID); - extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA); - - if (add_slot_str == NULL || caller_pid == NULL) - return -1; - - lid = __make_loader_id(); - size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid); - loader_name = (char *)malloc(size + 1); - if (loader_name == NULL) { - _E("Out of memory"); - return -1; - } - - snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid); - - slot_info.type = LAUNCHPAD_LOADER_TYPE_DYNAMIC; - slot_info.loader_id = lid; - slot_info.caller_pid = atoi(caller_pid); - slot_info.loader_name = loader_name; - slot_info.loader_path = add_slot_str; - slot_info.loader_extra = extra; - slot_info.detection_method = METHOD_TIMEOUT | METHOD_VISIBILITY; - slot_info.activation_method = METHOD_REQUEST | METHOD_AVAILABLE_MEMORY; - slot_info.deactivation_method = METHOD_TTL | METHOD_OUT_OF_MEMORY; - slot_info.ttl = 600; - slot_info.timeout_val = 2000; - slot_info.threshold_max = DEFAULT_CPU_THRESHOLD_MAX; - slot_info.threshold_min = DEFAULT_CPU_THRESHOLD_MIN; - slot_info.on_boot = false; - slot_info.app_exists = true; - slot_info.is_hydra = false; - slot_info.app_check = true; - slot_info.on_boot_timeout = 0; - slot_info.sched_priority = 0; - - cpc = __add_slot(&slot_info); - free(loader_name); - if (cpc == NULL) - return -1; - - __set_timer(cpc); - return lid; -} - -static int __dispatch_cmd_add_app_defined_loader(bundle *kb) -{ - const char *loader_name; - int lid, len; - candidate_process_context_t *cpc; - loader_info_t *info; - bundle_raw *extra; - slot_info_t slot_info; - - _W("cmd add defined loader"); - loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME); - - if (loader_name == NULL) { - _E("loader_name is NULL"); - return -EINVAL; - } - - info = _loader_info_find_loader_by_loader_name( - app_defined_loader_info_list, loader_name); - if (info == NULL || info->extra == NULL) { - _E("loader_name %s, info %d", loader_name, info != NULL); - return -EINVAL; - } - - - cpc = __find_slot_from_loader_name(loader_name); - if (cpc == NULL) { - lid = __make_loader_id(); - bundle_encode(info->extra, &extra, &len); - slot_info.type = LAUNCHPAD_LOADER_TYPE_DYNAMIC; - slot_info.loader_id = lid; - slot_info.caller_pid = 0; - 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 = METHOD_TIMEOUT | METHOD_VISIBILITY; - slot_info.activation_method = - METHOD_REQUEST | METHOD_AVAILABLE_MEMORY; - slot_info.deactivation_method = - METHOD_TTL | METHOD_OUT_OF_MEMORY; - slot_info.ttl = info->ttl; - slot_info.timeout_val = 2000; - slot_info.threshold_max = DEFAULT_CPU_THRESHOLD_MAX; - slot_info.threshold_min = DEFAULT_CPU_THRESHOLD_MIN; - slot_info.on_boot = false; - slot_info.app_exists = true; - slot_info.is_hydra = false; - slot_info.app_check = true; - slot_info.on_boot_timeout = 0; - slot_info.sched_priority = 0; - - cpc = __add_slot(&slot_info); - bundle_free_encoded_rawdata(&extra); - if (cpc == NULL) { - _E("cpc is NULL"); - return -ENOMEM; - } - } else { - lid = cpc->loader_id; - } - - if (cpc->pid == CANDIDATE_NONE) - __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid); - - return lid; -} - -static int __dispatch_cmd_remove_loader(bundle *kb) -{ - const char *id = bundle_get_val(kb, AUL_K_LOADER_ID); - int lid; - - _W("cmd remove loader"); - if (id) { - lid = atoi(id); - if (__remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid) == 0) - return 0; - } - - return -1; -} - -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) - return -1; - - if (strcmp(buf, "User") == 0 || - strcmp(buf, "System") == 0 || - strcmp(buf, "System::Privileged") == 0) - return 0; - - return -1; -} - -static bool __is_hw_acc(const char *hwacc) -{ - if (strcmp(hwacc, "USE") == 0 || - (strcmp(hwacc, "SYS") == 0 && - __sys_hwacc == SETTING_HW_ACCELERATION_ON)) - return true; - - return false; -} - -static candidate_process_context_t *__find_available_slot(const char *hwacc, - const char *app_type, const char *loader_name, - candidate_process_context_t **org_cpc) -{ - int type; - candidate_process_context_t *cpc; - int *a_types; - int len = 0; - int i; - - if (loader_name) { - type = _loader_info_find_type_by_loader_name(loader_info_list, - loader_name); - } else { - type = _loader_info_find_type(loader_info_list, - app_type, __is_hw_acc(hwacc)); - } - cpc = __find_slot(type, PAD_LOADER_ID_STATIC); - if (!cpc) - return NULL; - - *org_cpc = cpc; - - if (cpc->prepared) - return cpc; - - a_types = _loader_get_alternative_types(loader_info_list, type, &len); - if (!a_types) - return NULL; - - for (i = 0; i < len; i++) { - cpc = __find_slot(a_types[i], PAD_LOADER_ID_STATIC); - if (!cpc) - continue; - if (cpc->prepared) { - free(a_types); - return cpc; - } - } - - free(a_types); - return NULL; -} - -static void __update_slot(int type, bool app_exists) -{ - candidate_process_context_t *cpc; - - cpc = __find_slot(type, PAD_LOADER_ID_STATIC); - if (!cpc) - return; - - cpc->app_exists = app_exists; - if (cpc->app_check && !cpc->app_exists) { - if (cpc->pid > 0) - __dispose_candidate_process(cpc); - __sequencer_remove_slot(cpc); - if (__sequencer_queue_is_empty()) - __sequencer_stop(); - } else { - if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) - return; - - if (!cpc->touched && !cpc->on_boot) - return; - - if (cpc->timer > 0) { - g_source_remove(cpc->timer); - cpc->timer = 0; - } - - if (cpc->pid == CANDIDATE_NONE) { - __sequencer_add_slot(cpc); - __sequencer_run(); - } - } -} - -static void __foreach_loader_info(loader_info_t *info, void *data) -{ - struct app_info *ai = (struct app_info *)data; - bool exist; - - exist = _loader_info_exist_app_type(info, ai->type); - if (!exist) - return; - - info->app_exists = ai->exists; - __update_slot(info->type, info->app_exists); -} - -static int __dispatch_cmd_update_app_type(bundle *b) -{ - int r; - struct app_info info; - const char *is_installed; - - info.type = bundle_get_val(b, AUL_K_APP_TYPE); - if (!info.type) - return -1; - - is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED); - if (is_installed && !strcmp(is_installed, "true")) - info.exists = true; - else - info.exists = false; - - _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists); - - r = _loader_info_foreach(loader_info_list, __foreach_loader_info, - &info); - if (r != 0) { - _E("Failed to retrieve loader info"); - return -1; - } - - return 0; -} - -static void __deactivate_slot(candidate_process_context_t *cpc) -{ - if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED) - return; - - cpc->state = CANDIDATE_PROCESS_STATE_PAUSED; - if (cpc->is_hydra) - __dispose_hydra_process(cpc); - else - __dispose_candidate_process(cpc); -} - -static void __activate_slot(candidate_process_context_t *cpc) -{ - if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) - return; - - cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; - if (!cpc->touched && !cpc->on_boot) - return; - - if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE) - return; - - if (cpc->detection_method & METHOD_TIMEOUT) - __set_timer(cpc); -} - -static void __update_slot_state(candidate_process_context_t *cpc, int method, - bool force) -{ - switch (method) { - case METHOD_OUT_OF_MEMORY: - if ((force || cpc->deactivation_method & method) && - __is_low_memory()) { - _W("Low memory, deactivate slot %d", cpc->type); - __deactivate_slot(cpc); - } else { - __activate_slot(cpc); - } - break; - case METHOD_TTL: - if (force || cpc->deactivation_method & method) - __deactivate_slot(cpc); - break; - case METHOD_AVAILABLE_MEMORY: - if (force || cpc->activation_method & method) - __activate_slot(cpc); - break; - case METHOD_REQUEST: - if (force || cpc->activation_method & method) - __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force); - break; - default: - __activate_slot(cpc); - break; - } -} - -static void __request_destroy(request_t *request) -{ - if (request == NULL) - return; - - if (request->clifd > -1) - close(request->clifd); - if (request->menu_info) - _appinfo_free(request->menu_info); - if (request->kb) - bundle_free(request->kb); - if (request->pkt) - free(request->pkt); - free(request); -} - -static int __request_create(int fd, request_t **request) -{ - struct ucred cr; - request_t *req; - - if (request == NULL) { - _E("Invalid parameter"); - return -EINVAL; - } - - req = calloc(1, sizeof(request_t)); - if (req == NULL) { - _E("calloc() is failed"); - return -ENOMEM; - } - - req->clifd = -1; - req->pkt = _accept_recv_pkt_raw(fd, &req->clifd, &cr); - if (req->pkt == NULL) { - _E("_accept_recv_pkt_raw() is failed"); - __request_destroy(req); - return -ECOMM; - } - - req->kb = bundle_decode(req->pkt->data, req->pkt->len); - if (req->kb == NULL) { - _E("bundle_decode() is failed"); - __real_send(req->clifd, -EINVAL); - req->clifd = -1; - __request_destroy(req); - return -EINVAL; - } - - req->cmd = req->pkt->cmd; - req->caller_pid = cr.pid; - req->caller_uid = cr.uid; - *request = req; - return 0; -} - -static void __request_send_result(request_h request, int result) -{ - if (request->clifd < 0) - return; - - __real_send(request->clifd, result); - request->clifd = -1; -} - -static int __visibility_request_handler(request_h request) -{ - int ret = __dispatch_cmd_hint(request->kb, METHOD_VISIBILITY); - - __request_send_result(request, ret); - _D("[PAD_CMD_VISIBILITY] result: %d", ret); - return ret; -} - -static int __add_loader_request_handler(request_h request) -{ - int ret = __dispatch_cmd_add_loader(request->kb); - - __request_send_result(request, ret); - _D("[PAD_CMD_ADD_LOADER] result: %d", ret); - return ret; -} - -static int __remove_loader_request_handler(request_h request) -{ - int ret = __dispatch_cmd_remove_loader(request->kb); - - __request_send_result(request, ret); - _D("[PAD_CMD_REMOVE_LOADER] result: %d", ret); - return ret; -} - -static int __make_default_slots_request_handler(request_h request) -{ - int ret = __add_default_slots(); - - __request_send_result(request, ret); - _D("[PAD_CMD_MAKE_DEFAULT_SLOTS] result: %d", ret); - return ret; -} - -static int __prepare_app_defined_loader_request_handler(request_h request) -{ - int ret = __dispatch_cmd_add_app_defined_loader(request->kb); - - __request_send_result(request, ret); - _D("[PAD_CMD_PREPARE_APP_DEFINED_LOADER] result: %d", ret); - return ret; -} - -static int __demand_request_handler(request_h request) -{ - int ret = __dispatch_cmd_hint(request->kb, METHOD_DEMAND); - - __request_send_result(request, ret); - _D("[PAD_CMD_DEMAND] result: %d", ret); - return ret; -} - -static int __ping_request_handler(request_h request) -{ - __request_send_result(request, getpid()); - _D("[PAD_CMD_PING] result: %d", getpid()); - return 0; -} - -static int __update_app_type_request_handler(request_h request) -{ - int ret = __dispatch_cmd_update_app_type(request->kb); - - _D("[PAD_CMD_UPDATE_APP_TYPE] result: %d", ret); - return ret; -} - -static int __connect_request_handler(request_h request) -{ - if (__client_fd != -1) - close(__client_fd); - - __client_fd = request->clifd; - request->clifd = -1; - _D("[PAD_CMD_CONNECT] client fd: %d", __client_fd); - return 0; -} - -static int __launch_request_prepare(request_h request) -{ - const appinfo_t *menu_info; - int type = -1; - - request->menu_info = _appinfo_create(request->kb); - if (request->menu_info == NULL) { - _E("_appinfo_create() is failed"); - return -1; - } - - request->app_path = _appinfo_get_app_path(request->menu_info); - if (request->app_path == NULL) { - _E("_appinfo_get_app_path() is failed"); - return -1; - } - - if (request->app_path[0] != '/') { - _E("app path is not absolute path"); - return -1; - } - - menu_info = request->menu_info; - if (menu_info->hwacc == NULL) { - _E("Failed to find HW acceeleration type"); - return -1; - } - - SECURE_LOGD("appid: %s", menu_info->appid); - SECURE_LOGD("exec: %s", menu_info->app_path); - SECURE_LOGD("comp_type: %s", menu_info->comp_type); - SECURE_LOGD("internal pool: %s", menu_info->internal_pool); - SECURE_LOGD("hwacc: %s", menu_info->hwacc); - SECURE_LOGD("app_type: %s", menu_info->app_type); - SECURE_LOGD("pkg_type: %s", menu_info->pkg_type); - - if (menu_info->comp_type && !strcmp(menu_info->comp_type, "svcapp")) { - request->loader_id = __get_loader_id(request->kb); - if (request->loader_id > PAD_LOADER_ID_DYNAMIC_BASE) { - type = LAUNCHPAD_LOADER_TYPE_DYNAMIC; - request->cpc = __find_slot(type, request->loader_id); - if (request->cpc && !request->cpc->prepared) - request->cpc = NULL; - } else { - 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")) { - request->loader_id = PAD_LOADER_ID_DIRECT; - } else { - request->loader_id = __get_loader_id(request->kb); - if (request->loader_id <= PAD_LOADER_ID_STATIC) { - request->cpc = __find_available_slot(menu_info->hwacc, - menu_info->app_type, - menu_info->loader_name, - &request->org_cpc); - } else { - type = LAUNCHPAD_LOADER_TYPE_DYNAMIC; - request->cpc = __find_slot(type, request->loader_id); - if (request->cpc && !request->cpc->prepared) - request->cpc = NULL; - } - } - - _modify_bundle(request->kb, request->caller_pid, request->menu_info, - request->cmd); - if (menu_info->appid == NULL) { - _E("Unable to get appid from app info"); - return -1; - } - - PERF("Getting package information & modifying bundle done"); - return 0; -} - -static void __launch_request_complete(request_h request) -{ - _memory_monitor_reset_timer(); - __request_send_result(request, request->pid); - - if (request->pid > 0) { - _dbus_send_app_launch_signal(request->pid, - request->menu_info->appid); - g_hash_table_insert(__pid_table, GINT_TO_POINTER(request->pid), - strdup(request->menu_info->appid)); - _log_print("[LAUNCH]", "pid(%7d) | appid(%s)", - request->pid, request->menu_info->appid); - } -} - -static void __handle_direct_launch(request_h request) -{ - if (request->org_cpc && (!request->org_cpc->app_check || - request->org_cpc->app_exists) && - request->org_cpc->pid == CANDIDATE_NONE && - !__sequencer_slot_exist(request->org_cpc)) { - if (request->org_cpc->timer > 0) { - g_source_remove(request->org_cpc->timer); - request->org_cpc->timer = 0; - } - - __update_slot_state(request->org_cpc, METHOD_REQUEST, true); - __set_timer(request->org_cpc); - } -} - -static void __fork_processing(request_h request) -{ - if (bundle_get_type(request->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) - _debug_init(); - - _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, NULL); - if (request->pid == -1) { - _E("Failed to create a child process. appid(%s)", - request->menu_info->appid); - } - - __request_send_result(request, request->pid); - _W("appid: %s, pid: %d", request->menu_info->appid, request->pid); - __handle_direct_launch(request); -} - -static int __launch_request_do(request_h request) -{ - if (request->loader_id == PAD_LOADER_ID_DIRECT || - request->cpc == NULL) { - __fork_processing(request); - return 0; - } - - _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); - return 0; -} - -static int __launch_request_handler(request_h request) -{ - int ret; - - traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH"); - INIT_PERF(kb); - PERF("Packet processing start"); - - ret = __launch_request_prepare(request); - if (ret < 0) { - traceEnd(TTRACE_TAG_APPLICATION_MANAGER); - __request_send_result(request, ret); - return ret; - } - - ret = __launch_request_do(request); - if (ret < 0) - request->pid = ret; - - __launch_request_complete(request); - traceEnd(TTRACE_TAG_APPLICATION_MANAGER); - _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", - request->menu_info->appid, request->pid); - return 0; -} - -static request_handler __request_handlers[] = { - [PAD_CMD_VISIBILITY] = __visibility_request_handler, - [PAD_CMD_ADD_LOADER] = __add_loader_request_handler, - [PAD_CMD_REMOVE_LOADER] = __remove_loader_request_handler, - [PAD_CMD_MAKE_DEFAULT_SLOTS] = __make_default_slots_request_handler, - [PAD_CMD_PREPARE_APP_DEFINED_LOADER] = - __prepare_app_defined_loader_request_handler, - [PAD_CMD_DEMAND] = __demand_request_handler, - [PAD_CMD_PING] = __ping_request_handler, - [PAD_CMD_UPDATE_APP_TYPE] = __update_app_type_request_handler, - [PAD_CMD_CONNECT] = __connect_request_handler, - [PAD_CMD_LAUNCH] = __launch_request_handler, -}; - -static bool __handle_launch_event(int fd, io_condition_e cond, void *data) -{ - request_t *request = NULL; - int ret; - - if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { - _E("fd(%d), condition(%d)", fd, cond); - g_idle_add(__launchpad_recovery_cb, __launchpad_channel); - __launchpad_channel = NULL; - return false; - } - - ret = __request_create(fd, &request); - if (ret != 0) - return true; - - _W("cmd(%d), caller(%d)", request->cmd, request->caller_pid); - if (request->caller_uid >= REGULAR_UID_MIN) { - if (__check_caller_by_pid(request->caller_pid) < 0) { - _E("Permission denied. pid(%d)", request->caller_pid); - __request_send_result(request, -EPERM); - __request_destroy(request); - return true; - } - } - - if (request->cmd < 0 || request->cmd >= ARRAY_SIZE(__request_handlers) - || __request_handlers[request->cmd] == NULL) { - _E("Unknown command: %d", request->cmd); - __request_send_result(request, -EINVAL); - __request_destroy(request); - return true; - } - - __request_handlers[request->cmd](request); - __request_destroy(request); - return true; -} - -static void __destroy_slot(candidate_process_context_t *cpc) -{ - if (!cpc) - return; - - if (cpc->hydra_channel) - _io_channel_destroy(cpc->hydra_channel); - - if (cpc->channel) - _io_channel_destroy(cpc->channel); - - if (cpc->loader_extra) - free(cpc->loader_extra); - - if (cpc->loader_path) - free(cpc->loader_path); - - if (cpc->loader_name) - free(cpc->loader_name); - - free(cpc); -} - -static candidate_process_context_t *__create_slot(slot_info_t *info) -{ - candidate_process_context_t *cpc; - - cpc = calloc(1, sizeof(candidate_process_context_t)); - if (cpc == NULL) { - _E("Out of memory"); - return NULL; - } - - cpc->loader_name = strdup(info->loader_name); - if (cpc->loader_name == NULL) { - _E("Failed to duplicate loader name(%s)", info->loader_name); - __destroy_slot(cpc); - return NULL; - } - - cpc->loader_path = strdup(info->loader_path); - if (cpc->loader_path == NULL) { - _E("Failed to duplicate loader path(%s)", info->loader_path); - __destroy_slot(cpc); - return NULL; - } - - cpc->loader_extra = - info->loader_extra ? strdup(info->loader_extra) : strdup(""); - if (cpc->loader_extra == NULL) { - _E("Failed to duplicate loader extra(%s)", info->loader_extra); - __destroy_slot(cpc); - return NULL; - } - - cpc->type = info->type; - cpc->prepared = false; - cpc->pid = CANDIDATE_NONE; - cpc->hydra_pid = HYDRA_NONE; - cpc->caller_pid = info->caller_pid; - cpc->loader_id = info->loader_id; - cpc->send_fd = -1; - cpc->hydra_fd = -1; - cpc->last_exec_time = 0; - cpc->timer = 0; - cpc->detection_method = info->detection_method; - cpc->timeout_val = info->timeout_val; - cpc->cpu_total_time = 0; - cpc->cpu_idle_time = 0; - cpc->threshold = info->threshold_max; - cpc->threshold_max = info->threshold_max; - cpc->threshold_min = info->threshold_min; - cpc->on_boot = info->on_boot; - cpc->app_exists = info->app_exists; - cpc->touched = false; - cpc->cur_event = 0; - cpc->activation_method = info->activation_method; - cpc->deactivation_method = info->deactivation_method; - cpc->ttl = info->ttl; - cpc->live_timer = 0; - cpc->is_hydra = info->is_hydra; - cpc->app_check = info->app_check; - cpc->score = WIN_SCORE; - cpc->pss = 0; - cpc->cpu_check_count = 0; - cpc->on_boot_timeout = info->on_boot_timeout; - cpc->sched_priority = info->sched_priority; - - if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) && - __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); - return cpc; -} - -static candidate_process_context_t *__add_slot(slot_info_t *info) -{ - candidate_process_context_t *cpc; - int fd; - io_channel_h channel; - int hydra_fd; - io_channel_h hydra_channel; - - if (info == NULL) - return NULL; - - if (__find_slot(info->type, info->loader_id) != NULL) - return NULL; - - cpc = __create_slot(info); - if (cpc == NULL) - return NULL; - - 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); - __destroy_slot(cpc); - return NULL; - } - - channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc); - if (!channel) { - close(fd); - __destroy_slot(cpc); - return NULL; - } - - cpc->channel = channel; - - 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); - __destroy_slot(cpc); - return NULL; - } - - hydra_channel = _io_channel_create(hydra_fd, IO_IN, - __handle_hydra_event, cpc); - if (!hydra_channel) { - close(hydra_fd); - __destroy_slot(cpc); - return NULL; - } - - cpc->hydra_channel = hydra_channel; - } - - candidate_slot_list = g_list_append(candidate_slot_list, cpc); - - return cpc; -} - -static int __remove_slot(int type, int loader_id) -{ - candidate_process_context_t *cpc; - GList *iter; - - iter = candidate_slot_list; - while (iter) { - cpc = (candidate_process_context_t *)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); - __destroy_slot(cpc); - return 0; - } - - iter = g_list_next(iter); - } - - return -1; -} - -static int __init_launchpad_fd(int argc, char **argv) -{ - io_condition_e cond; - int fd; - - fd = __launchpad_pre_init(argc, argv); - if (fd < 0) { - _E("launchpad pre init failed"); - return -1; - } - - cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL; - __launchpad_channel = _io_channel_create(fd, cond, - __handle_launch_event, NULL); - if (!__launchpad_channel) { - close(fd); - return -1; - } - - return 0; -} - -static bool __on_directory_create(const char *event_name, uint32_t mask, - void *user_data) -{ - if (!event_name) { - _E("Invalid parameter"); - return true; - } - - if (!strcmp(event_name, LOADERS_PATH)) { - _W("%s is created", LOADERS_PATH); - __init_app_defined_loader_monitor(); - return false; - } - - return true; -} - -static bool __on_file_change(const char *event_name, uint32_t mask, - void *user_data) -{ - char buf[PATH_MAX]; - char *ext; - loader_info_t* info; - candidate_process_context_t *cpc; - - if (!event_name) { - _E("Invalid parameter"); - return true; - } - - ext = strrchr(event_name, '.'); - if (ext == NULL || strcmp(ext, ".loader") != 0) - return true; - - _W("event_name(%s), mask(%u)", event_name, mask); - if (mask & IN_CREATE) { - snprintf(buf, sizeof(buf), "%s/%s", - APP_DEFINED_LOADER_INFO_PATH, event_name); - app_defined_loader_info_list = _loader_info_load_file( - app_defined_loader_info_list, buf); - } else if (mask & IN_DELETE) { - snprintf(buf, ext - event_name + 1, "%s", event_name); - - info = _loader_info_find_loader_by_loader_name( - app_defined_loader_info_list, buf); - cpc = __find_slot_from_loader_name(info->name); - __remove_slot(cpc->type, cpc->loader_id); - app_defined_loader_info_list = _loader_info_unload( - app_defined_loader_info_list, buf); - } - - return true; -} - -static void __init_app_defined_loader_monitor(void) -{ - int ret; - - ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK); - 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, NULL); - if (ret != 0) - _E("Failed to add inotify watch %s", OPT_SHARE_PATH); - - return; - } - - ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH, - IN_CREATE | IN_DELETE, __on_file_change, NULL); - - if (ret < 0) { - _E("Failed to add inotify watch %s", - APP_DEFINED_LOADER_INFO_PATH); - } - - return; - -} - -static int __init_label_monitor_fd(void) -{ - io_condition_e cond; - int r; - int fd = -1; - - r = security_manager_app_labels_monitor_init(&label_monitor); - if (r != SECURITY_MANAGER_SUCCESS) - return -1; - - r = security_manager_app_labels_monitor_process(label_monitor); - if (r != SECURITY_MANAGER_SUCCESS) - goto err; - - security_manager_app_labels_monitor_get_fd(label_monitor, &fd); - if (fd < 0) { - _E("failed to get fd"); - goto err; - } - - cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL; - __label_monitor_channel = _io_channel_create(fd, cond, - __handle_label_monitor, NULL); - if (!__label_monitor_channel) - goto err; - - return 0; - -err: - if (fd > 0) - close(fd); - - if (label_monitor) { - security_manager_app_labels_monitor_finish(label_monitor); - label_monitor = NULL; - } - - return -1; -} - -static int __verify_loader_caps(const char *loader) -{ - cap_t cap_d; - cap_flag_value_t eff_state; - cap_flag_value_t inh_state; - cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN}; - int r; - int i; - int size = ARRAY_SIZE(values); - - /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */ - if (label_monitor) - size--; - - cap_d = cap_get_file(loader); - if (!cap_d) { - _E("Failed to get cap from file(%s)", loader); - return -1; - } - - for (i = 0; i < size; i++) { - r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state); - if (r != 0) { - _E("Failed to get cap inh - errno(%d)", errno); - cap_free(cap_d); - return -1; - } - - r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state); - if (r != 0) { - _E("Failed to get cap eff - errno(%d)", errno); - cap_free(cap_d); - return -1; - } - - if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) { - _E("The %s doesn't have %d cap", loader, values[i]); - cap_free(cap_d); - return -1; - } - } - cap_free(cap_d); - - return 0; -} - -static void __get_app_type_string(loader_info_t *info, char buf[], int size) -{ - GList *iter = info->app_types; - char *app_type; - char *ptr = buf; - int len; - - while (iter) { - app_type = (char *)iter->data; - iter = g_list_next(iter); - len = strlen(app_type); - if (size < len + 1) - return; - - strncpy(ptr, app_type, size); - ptr += len; - size -= len; - if (iter) { - (*ptr++) = ' '; - size--; - } - } -} - -static void __add_slot_from_info(gpointer data, gpointer user_data) -{ - loader_info_t *info = (loader_info_t *)data; - candidate_process_context_t *cpc; - bundle_raw *extra = NULL; - int len; - char buf[2048] = {0, }; - slot_info_t slot_info = { - .type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset, - .loader_name = info->name, - .loader_path = info->exe, - .threshold_max = info->cpu_threshold_max, - .threshold_min = info->cpu_threshold_min, - .app_exists = info->app_exists, - .is_hydra = info->is_hydra, - .app_check = info->app_check, - .on_boot_timeout = info->on_boot_timeout, - .sched_priority = info->sched_priority, - }; - - if (!strcmp(info->exe, "null")) { - slot_info.loader_id = PAD_LOADER_ID_DIRECT; - - cpc = __add_slot(&slot_info); - if (cpc == NULL) - return; - - info->type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset; - user_slot_offset++; - return; - } - - if (access(info->exe, F_OK | X_OK) == 0) { - if (__verify_loader_caps(info->exe) < 0) - return; - - if (info->extra) - bundle_encode(info->extra, &extra, &len); - - slot_info.loader_id = PAD_LOADER_ID_STATIC; - slot_info.loader_extra = (const char *)extra; - slot_info.detection_method = info->detection_method; - slot_info.activation_method = info->activation_method; - slot_info.deactivation_method = info->deactivation_method; - slot_info.ttl = info->ttl; - slot_info.timeout_val = info->timeout_val; - slot_info.on_boot = info->on_boot; - - cpc = __add_slot(&slot_info); - bundle_free_encoded_rawdata(&extra); - if (cpc == NULL) - return; - - info->type = LAUNCHPAD_LOADER_TYPE_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, info->type); - _print_hwc_log("candidate slot. app-type(%s) loader-type(%d)", - buf, info->type); - } -} - -static int __add_default_slots(void) -{ - if (loader_info_list) - _loader_info_dispose(loader_info_list); - - loader_info_list = _loader_info_load_dir(LOADER_INFO_PATH); - if (loader_info_list == NULL) - return -1; - - user_slot_offset = 0; - g_list_foreach(loader_info_list, __add_slot_from_info, NULL); - __add_idle_checker(0, candidate_slot_list); - - return 0; -} - -static void __add_app_defined_loaders(void) -{ - app_defined_loader_info_list = _loader_info_load_dir(APP_DEFINED_LOADER_INFO_PATH); -} - -static bool __is_low_memory(void) -{ - if (_memory_monitor_is_low_memory()) - return true; - - if (__memory_status_low >= MEMORY_STATUS_LOW) - return true; - - return false; -} - -static void __hw_acceleration_changed_cb(keynode_t *key, void *data) -{ - __sys_hwacc = vconf_keynode_get_int(key); - _D("sys hwacc: %d", __sys_hwacc); -} - -static void __update_lang(keynode_t *node, void *user_data) -{ - char *lang; - - lang = vconf_keynode_get_str(node); - if (!lang) { - _E("Failed to get language"); - return; - } - - setenv("LANG", lang, 1); -} - -static void __region_format_changed_cb(keynode_t *node, void *data) -{ - char *region; - - region = vconf_keynode_get_str(node); - if (!region) { - _E("Failed to get value"); - return; - } - - setenv("LC_CTYPE", region, 1); -} - -static void __memory_status_low_changed_cb(keynode_t *node, void *data) -{ - candidate_process_context_t *cpc; - GList *iter; - - __memory_status_low = vconf_keynode_get_int(node); - if (__memory_status_low >= MEMORY_STATUS_LOW) { - _W("Low memory"); - iter = candidate_slot_list; - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, false); - iter = g_list_next(iter); - } - } -} - -static void __memory_status_normal_changed_cb(keynode_t *node, void *data) -{ - candidate_process_context_t *cpc; - GList *iter; - - __memory_status_normal = vconf_keynode_get_int(node); - if (__memory_status_normal == MEMORY_STATUS_NORMAL) { - _W("Normal"); - iter = candidate_slot_list; - while (iter) { - cpc = (candidate_process_context_t *)iter->data; - __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true); - iter = g_list_next(iter); - } - } -} - -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); - - 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); -} - -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) - _E("Failed to get vconf hw acceleration. err = %d", r); - - r = vconf_notify_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, - __hw_acceleration_changed_cb, NULL); - if (r != VCONF_OK) { - _E("Failed to register callback for hw acceleration. err = %d", - r); - } - - lang = vconf_get_str(VCONFKEY_LANGSET); - if (lang) { - setenv("LANG", lang, 1); - free(lang); - } - - r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL); - if (r != VCONF_OK) - _E("Failed to register callback for langset. err = %d", r); - - region = vconf_get_str(VCONFKEY_REGIONFORMAT); - if (region) { - setenv("LC_CTYPE", region, 1); - free(region); - } - - r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, - __region_format_changed_cb, NULL); - 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); - 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, NULL); - 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); - 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, NULL); - if (r != 0) - _E("Failed to register callback for normal memory. err = %d", r); - - return 0; -} - -static bool __handle_logger(int fd, io_condition_e cond, void *data) -{ - app_pkt_t *pkt; - struct ucred cr; - int clifd = -1; - - if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { - _E("fd(%d), io_condition(%d)", fd, cond); - g_idle_add(__logger_recovery_cb, __logger_channel); - __logger_channel = NULL; - return false; - } - - pkt = _accept_recv_pkt_raw(fd, &clifd, &cr); - if (!pkt) { - _E("Failed to receive the packet"); - return true; - } - - if (getuid() != cr.uid) { - _E("Invalid caller"); - goto end; - } - - if (pkt->len <= 0) { - _E("Invalid message"); - goto end; - } - - _E("[%d] %s", cr.pid, (const char *)pkt->data); - _log_print("[ERROR]", "pid(%7d) | message(%s)", - cr.pid, (const char *)pkt->data); -end: - if (clifd != -1) - close(clifd); - - free(pkt); - - return true; -} - -static int __init_logger_fd(void) -{ - io_condition_e cond; - int fd; - - fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK); - if (fd < 0) { - _E("Failed to create logger socker"); - return -1; - } - - cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; - __logger_channel = _io_channel_create(fd, cond, __handle_logger, NULL); - if (!__logger_channel) { - close(fd); - return -1; - } - - 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; - - if (low_memory) { - _W("Low memory"); - __update_slots_pss(); - - candidate_slot_list = g_list_sort(candidate_slot_list, - __compare_slot); - __pause_all_running_slots(false); - } else { - __resume_all_slots(); - } - - return 0; -} - -static gboolean __logger_recovery_cb(gpointer data) -{ - io_channel_h channel = data; - int ret; - - _io_channel_destroy(channel); - - ret = __init_logger_fd(); - if (ret < 0) { - _E("Failed to recover logger socket"); - return G_SOURCE_REMOVE; - } - - _E("[__RECOVERY__] Logger socket"); - - return G_SOURCE_REMOVE; -} - -static gboolean __launchpad_recovery_cb(gpointer data) -{ - io_channel_h channel = data; - int ret; - - _io_channel_destroy(channel); - - ret = __init_launchpad_fd(0, NULL); - if (ret < 0) { - _E("Failed to recover launchpad socket"); - abort(); - return G_SOURCE_REMOVE; - } - - _E("[__RECOVERY__] Launchpad socket"); - - return G_SOURCE_REMOVE; -} - -static int __before_loop(int argc, char **argv) -{ - int ret; - - _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__); - ret = __sequencer_init(); - if (ret < 0) { - _E("Failed to initialize sequencer"); - return -1; - } - - ret = _signal_init(); - if (ret < 0) { - _E("Failed to initialize signal"); - return -1; - } - - _signal_set_sigchld_cb(__handle_sigchild, NULL); - - ret = __init_launchpad_fd(argc, argv); - if (ret != 0) { - _E("__init_launchpad_fd() failed"); - return -1; - } - - ret = __init_logger_fd(); - if (ret != 0) { - _E("__init_logger_fd() failed"); - return -1; - } - - ret = __init_label_monitor_fd(); - if (ret != 0) - _W("Failed to initialize label monitor"); - - ret = _config_init(); - if (ret != 0) - _W("Failed to initialize config"); - - ret = _dbus_init(); - if (ret != 0) - _W("Failed to initialize dbus"); - - _inotify_init(); - - MAX_CPU_CHECK_COUNT = _config_get_int_value( - CONFIG_TYPE_CPU_CHECKER_MAX_COUNT); - __add_default_slots(); - launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH); - - __add_app_defined_loaders(); - - ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL); - if (ret < 0) - _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL); - - __pid_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, - NULL, free); - if (!__pid_table) { - _E("Failed to create pid table"); - return -1; - } - - ret = _worker_create("cleaner+", &__cleaner); - if (ret < 0) - return ret; - - __register_vconf_events(); - __init_app_defined_loader_monitor(); - _memory_monitor_init(); - _memory_monitor_set_event_cb(__memory_monitor_cb, NULL); - _log_init(); - _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__); - - return 0; -} - -static void __after_loop(void) -{ - _log_fini(); - _memory_monitor_fini(); - __unregister_vconf_events(); - _worker_destroy(__cleaner); - if (__pid_table) - g_hash_table_destroy(__pid_table); - - if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0) - _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL); - - _debug_fini(); - _launcher_info_unload(launcher_info_list); - _dbus_fini(); - _config_fini(); - _inotify_fini(); - _loader_info_dispose(app_defined_loader_info_list); - - if (__label_monitor_channel) - _io_channel_destroy(__label_monitor_channel); - - if (label_monitor) - security_manager_app_labels_monitor_finish(label_monitor); - - if (__logger_channel) - _io_channel_destroy(__logger_channel); - - if (__launchpad_channel) - _io_channel_destroy(__launchpad_channel); - - _signal_fini(); - - __sequencer_fini(); -} - -int main(int argc, char **argv) -{ - GMainLoop *mainloop = NULL; - - _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__); - prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); - - mainloop = g_main_loop_new(NULL, FALSE); - if (!mainloop) { - _E("Failed to create glib main loop"); - return -1; - } - - _print_hwc_log("%s(%d): __before_loop()", __FUNCTION__, __LINE__); - if (__before_loop(argc, argv) != 0) { - _E("process-pool Initialization failed!"); - return -1; - } - -#ifdef TIZEN_FEATURE_PRIORITY_CHANGE - _set_priority(-12); -#endif - _print_hwc_log("%s(%d): g_main_loop_run()", __FUNCTION__, __LINE__); - g_main_loop_run(mainloop); - - __after_loop(); - - return -1; -} diff --git a/src/launchpad-process-pool/src/launchpad.cc b/src/launchpad-process-pool/src/launchpad.cc new file mode 100644 index 0000000..a71168f --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad.cc @@ -0,0 +1,3451 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "key.h" +#include "launcher_info.hh" +#include "launchpad_common.h" +#include "launchpad_config.h" +#include "launchpad_dbus.h" +#include "launchpad_debug.h" +#include "launchpad_inotify.h" +#include "launchpad_io_channel.h" +#include "launchpad_log.h" +#include "launchpad_memory_monitor.h" +#include "launchpad_plugin.h" +#include "launchpad_proc.h" +#include "launchpad_signal.h" +#include "launchpad_types.h" +#include "launchpad_worker.h" +#include "loader_info.hh" +#include "perf.h" +#include "slot_info.h" + +#define AUL_PR_NAME 16 +#define EXEC_CANDIDATE_EXPIRED 5 +#define EXEC_CANDIDATE_WAIT 1 +#define DIFF(a, b) (((a) > (b)) ? (a) - (b) : (b) - (a)) +#define CANDIDATE_NONE 0 +#define HYDRA_NONE 0 +#define PROCESS_POOL_LAUNCHPAD_SOCK ".launchpad-process-pool-sock" +#define LAUNCHPAD_LOGGER_SOCK ".launchpad-logger-sock" +#define LOADER_PATH_DEFAULT "/usr/bin/launchpad-loader" +#define LOADER_INFO_PATH "/usr/share/aul" +#define OPT_SHARE_PATH "/opt/share" +#define LOADERS_PATH "loaders" +#define APP_DEFINED_LOADER_INFO_PATH OPT_SHARE_PATH "/" LOADERS_PATH +#define COMMON_LOADER_NAME "common-loader1" + +#define LAUNCHER_INFO_PATH LOADER_INFO_PATH +#define REGULAR_UID_MIN 5000 +#define PAD_ERR_FAILED -1 +#define PAD_ERR_REJECTED -2 +#define PAD_ERR_INVALID_ARGUMENT -3 +#define PAD_ERR_INVALID_PATH -4 +#define CPU_CHECKER_TIMEOUT 1000 +#define PI 3.14159265 +#define WIN_SCORE 100 +#define LOSE_SCORE_RATE 0.7f + +enum candidate_process_state_e { + CANDIDATE_PROCESS_STATE_RUNNING, + CANDIDATE_PROCESS_STATE_PAUSED, +}; + +typedef struct { + int type; + bool prepared; + int pid; /* 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; +} candidate_process_context_t; + +typedef struct { + GPollFD* gpollfd; + int type; + int loader_id; +} loader_context_t; + +typedef struct { + GQueue* queue; + guint timer; + guint idle_checker; + candidate_process_context_t* running_cpc; +} sequencer; + +struct app_launch_arg { + const char* appid; + const char* app_path; + appinfo_t* menu_info; + bundle* kb; +}; + +struct app_arg { + int argc; + char** argv; +}; + +struct app_info { + const char* type; + bool exists; +}; + +struct cleanup_info_s { + char* appid; + int pid; +}; + +typedef struct candidate_info_s { + char** argv; + int argc; + int loader_id; + int type; + pid_t pid; +} candidate_info_t; + +typedef struct request_s { + app_pkt_t* pkt; + appinfo_t* menu_info; + bundle* kb; + candidate_process_context_t* cpc; + candidate_process_context_t* org_cpc; + const char* app_path; + int clifd; + int cmd; + int loader_id; + pid_t caller_pid; + uid_t caller_uid; + pid_t pid; /* result */ +} request_t; + +typedef request_t* request_h; + +typedef int (*request_handler)(request_h request); + +namespace { + +int __sys_hwacc; +std::unique_ptr loader_info_manager; +std::unique_ptr app_defined_loader_info_manager; +int user_slot_offset; +GList* candidate_slot_list; +app_labels_monitor* label_monitor; +std::vector launcher_info_list; +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; +int __client_fd = -1; +worker_h __cleaner; + +} // namespace + +static candidate_process_context_t* __add_slot(slot_info_t* info); +static int __remove_slot(int type, int loader_id); +static int __add_default_slots(void); +static gboolean __handle_idle_checker(gpointer data); +static int __add_idle_checker(int detection_method, GList* cur); +static void __dispose_candidate_process(candidate_process_context_t* cpc); +static bool __is_low_memory(void); +static void __update_slot_state(candidate_process_context_t* cpc, + launchpad::LoaderMethod method, + bool force); +static void __init_app_defined_loader_monitor(void); +static gboolean __launchpad_recovery_cb(gpointer data); +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; + + if (__sequencer.idle_checker > 0) + return G_SOURCE_CONTINUE; + + if (g_queue_is_empty(__sequencer.queue)) { + __sequencer.timer = 0; + return G_SOURCE_REMOVE; + } + + cpc = (candidate_process_context_t*)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) { + _W("The application is not installed. Type(%d)", cpc->type); + return G_SOURCE_CONTINUE; + } + + if (cpc->timer) { + g_source_remove(cpc->timer); + cpc->timer = 0; + } + + if (cpc->pid != CANDIDATE_NONE) { + _W("The slot(%d) is already running. pid(%d)", cpc->type, cpc->pid); + return G_SOURCE_CONTINUE; + } + + _get_cpu_idle(&total, &idle); + cpc->cpu_idle_time = idle; + cpc->cpu_total_time = total; + cpc->cpu_check_count = 0; + + __sequencer.idle_checker = + g_timeout_add(CPU_CHECKER_TIMEOUT, __handle_idle_checker, cpc); + __sequencer.running_cpc = cpc; + + _W("[__SEQUENCER__] Add idle checker. Type(%d)", cpc->type); + + return G_SOURCE_CONTINUE; +} + +static bool __sequencer_slot_is_running(candidate_process_context_t* cpc) { + if (__sequencer.running_cpc == cpc) + return true; + + return false; +} + +static bool __sequencer_slot_exist(candidate_process_context_t* cpc) { + GList* found; + + found = g_queue_find(__sequencer.queue, cpc); + if (found) + return true; + + return false; +} + +static int __sequencer_add_slot(candidate_process_context_t* cpc) { + if (__sequencer_slot_exist(cpc)) { + _W("Already exists"); + return -1; + } + + if (__sequencer_slot_is_running(cpc)) { + _W("slot(%d) is running", cpc->type); + return -1; + } + + g_queue_push_tail(__sequencer.queue, cpc); + + return 0; +} + +static void __sequencer_remove_slot(candidate_process_context_t* cpc) { + g_queue_remove(__sequencer.queue, cpc); +} + +static void __sequencer_run(void) { + if (__sequencer.timer) + return; + + __sequencer.timer = g_timeout_add(500, __handle_queuing_slots, nullptr); + if (!__sequencer.timer) + _E("Failed to add sequencer timer"); +} + +static void __sequencer_stop(void) { + if (!__sequencer.timer) + return; + + g_source_remove(__sequencer.timer); + __sequencer.timer = 0; +} + +static bool __sequencer_queue_is_empty(void) { + if (g_queue_is_empty(__sequencer.queue)) + return true; + + return false; +} + +static int __sequencer_init(void) { + _D("[__SEQUENCER__] Init"); + + __sequencer.queue = g_queue_new(); + if (!__sequencer.queue) { + _E("Out of memory"); + return -1; + } + + return 0; +} + +static void __sequencer_fini(void) { + _D("[__SEQUENCER__] Finish"); + + if (__sequencer.idle_checker > 0) + g_source_remove(__sequencer.idle_checker); + + if (__sequencer.timer > 0) + g_source_remove(__sequencer.timer); + + g_queue_free(__sequencer.queue); +} + +static int __make_loader_id(void) { + static int id = PAD_LOADER_ID_DYNAMIC_BASE; + + return ++id; +} + +static candidate_process_context_t* __find_slot_from_static_type(int type) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + if (type == static_cast(launchpad::LoaderType::Dynamic) || + type == static_cast(launchpad::LoaderType::Unsupported)) + return nullptr; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (type == cpc->type) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static candidate_process_context_t* __find_slot_from_pid(int pid) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (pid == cpc->pid) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static candidate_process_context_t* __find_hydra_slot_from_pid(int pid) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (cpc->is_hydra && pid == cpc->hydra_pid) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static candidate_process_context_t* __find_slot_from_caller_pid( + int caller_pid) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (caller_pid == cpc->caller_pid) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static candidate_process_context_t* __find_slot_from_loader_id(int id) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (id == cpc->loader_id) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static candidate_process_context_t* __find_slot_from_loader_name( + const char* loader_name) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (strcmp(cpc->loader_name, loader_name) == 0) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static candidate_process_context_t* __find_slot(int type, int loader_id) { + if (type == static_cast(launchpad::LoaderType::Dynamic)) + return __find_slot_from_loader_id(loader_id); + + return __find_slot_from_static_type(type); +} + +static void __update_slot_score(candidate_process_context_t* slot) { + if (!slot) + return; + + slot->score *= LOSE_SCORE_RATE; + slot->score += WIN_SCORE; +} + +static void __update_slots_pss(void) { + candidate_process_context_t* cpc; + GList* iter; + + iter = candidate_slot_list; + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + iter = g_list_next(iter); + + if (cpc->pid == CANDIDATE_NONE) + continue; + + _proc_get_mem_pss(cpc->pid, &cpc->pss); + } +} + +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; + + if (slot_a->is_hydra && !slot_b->is_hydra) + return -1; + if (!slot_a->is_hydra && slot_b->is_hydra) + return 1; + + if (slot_a->score < slot_b->score) + return 1; + if (slot_a->score > slot_b->score) + return -1; + + if (slot_a->pss < slot_b->pss) + return -1; + if (slot_a->pss > slot_b->pss) + return 1; + + return 0; +} + +static candidate_process_context_t* __get_running_slot(bool is_hydra) { + candidate_process_context_t* cpc; + GList* iter; + + iter = candidate_slot_list; + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (cpc->is_hydra == is_hydra && cpc->pid != CANDIDATE_NONE) + return cpc; + + iter = g_list_next(iter); + } + + return nullptr; +} + +static void __pause_all_running_slots(bool is_hydra) { + candidate_process_context_t* cpc = nullptr; + GList* iter; + + iter = g_list_last(candidate_slot_list); + while (iter) { + cpc = (candidate_process_context_t*)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()) + return; + } + + iter = g_list_previous(iter); + } +} + +static void __resume_all_slots(void) { + candidate_process_context_t* cpc; + GList* iter; + + iter = candidate_slot_list; + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true); + + iter = g_list_next(iter); + } +} + +static void __kill_process(int pid) { + char err_str[MAX_LOCAL_BUFSZ] = { + 0, + }; + + if (kill(pid, SIGKILL) == -1) { + _E("send SIGKILL: %s", strerror_r(errno, err_str, sizeof(err_str))); + } +} + +static void __refuse_candidate_process(int server_fd) { + int client_fd = -1; + + if (server_fd == -1) { + _E("arguments error!"); + goto error; + } + + client_fd = accept(server_fd, nullptr, nullptr); + if (client_fd == -1) { + _E("accept error!"); + goto error; + } + + close(client_fd); + _D("refuse connection!"); + +error: + return; +} + +static int __accept_candidate_process(int server_fd, + int* out_client_fd, + int* out_client_pid, + int cpc_pid) { + int client_fd = -1; + int recv_pid = 0; + int ret; + socklen_t len; + struct ucred cred = {}; + + if (server_fd == -1 || out_client_fd == nullptr || + out_client_pid == nullptr) { + _E("arguments error!"); + goto error; + } + + client_fd = accept(server_fd, nullptr, nullptr); + if (client_fd == -1) { + _E("accept error!"); + goto error; + } + + if (_set_sock_option(client_fd, 1) < 0) { + _E("Failed to set sock option"); + goto error; + } + + ret = recv(client_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL); + if (ret == -1) { + _E("recv error!"); + goto error; + } + + len = (socklen_t)sizeof(cred); + ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &len); + if (ret < 0) { + _E("getsockopt error"); + goto error; + } + + if (cpc_pid != -1 && cred.pid != cpc_pid) { + _E("Invalid accept. pid(%d)", cred.pid); + goto error; + } + + if (cred.pid != recv_pid) + _W("Not equal recv and real pid"); + + *out_client_fd = client_fd; + *out_client_pid = cred.pid; + + return *out_client_fd; + +error: + if (client_fd != -1) + close(client_fd); + + return -1; +} + +static int __listen_addr(struct sockaddr_un* addr) { + int fd = -1; + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + _E("Socket error"); + goto error; + } + + unlink(addr->sun_path); + + _D("bind to %s", addr->sun_path); + if (bind(fd, (struct sockaddr*)addr, sizeof(struct sockaddr_un)) < 0) { + _E("bind error"); + goto error; + } + + _D("listen to %s", addr->sun_path); + if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) { + _E("listen error"); + goto error; + } + + SECURE_LOGD("[launchpad] done, listen fd: %d", fd); + return fd; + +error: + if (fd != -1) + close(fd); + + return -1; +} + +static int __listen_candidate_process(int type, int loader_id) { + struct sockaddr_un addr; + + _D("[launchpad] enter, type: %d", type); + + 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); + + return __listen_addr(&addr); +} + +static int __listen_hydra_process(int type, int loader_id) { + struct sockaddr_un addr; + + _D("[launchpad] enter, type: %d", type); + + 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); + + return __listen_addr(&addr); +} + +static int __get_loader_id(bundle* kb) { + const char* val; + + val = bundle_get_val(kb, AUL_K_LOADER_ID); + if (val == nullptr) + return -1; + _W("Requested loader id: %s", val); + + return atoi(val); +} + +static int __candidate_process_real_launch(int candidate_fd, app_pkt_t* pkt) { + return _send_pkt_raw(candidate_fd, pkt); +} + +static int __real_send(int clifd, int ret) { + if (clifd < 3) { + _E("Invalid parameter. clifd(%d)", clifd); + return -1; + } + + if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) { + if (errno == EPIPE) { + _E("send failed due to EPIPE."); + close(clifd); + return -1; + } + _E("send fail to client"); + } + + close(clifd); + return 0; +} + +static int __fork_app_process(int (*child_fn)(void*), void* arg, + int sched_priority) { + int pid; + int ret; + + pid = fork(); + if (pid == -1) { + _E("failed to fork child process"); + return -1; + } + + if (pid == 0) { + if (sched_priority != 0) + _set_priority(sched_priority); + + _W("security_manager_prepare_app_candidate ++"); + ret = security_manager_prepare_app_candidate(); + _W("security_manager_prepare_app_candidate --"); + if (ret != SECURITY_MANAGER_SUCCESS) { + _E("failed to prepare app candidate process (%d)", ret); + exit(1); + } + + ret = child_fn(arg); + _E("failed to exec app process (%d)", errno); + exit(ret); + } + + return pid; +} + +static int __exec_loader_process(void* arg) { + char** argv = static_cast(arg); + char err_buf[1024]; + + _signal_unblock_sigchld(); + _close_all_fds(); + _setup_stdio(basename(argv[LOADER_ARG_PATH])); + + 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))); + } else { + _D("Succeeded to prepare candidate_process"); + } + + return -1; +} + +static gboolean __handle_deactivate_event(gpointer user_data) { + candidate_process_context_t* cpc; + + cpc = (candidate_process_context_t*)user_data; + __update_slot_state(cpc, launchpad::LoaderMethod::Ttl, false); + _D("Deactivate event: type(%d)", cpc->type); + + return G_SOURCE_REMOVE; +} + +static void __set_live_timer(candidate_process_context_t* cpc) { + if (!cpc) + return; + + 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); + } + } +} + +static int __hydra_send_request(int fd, enum hydra_cmd cmd) { + int sent = 0; + int size = (int)sizeof(cmd); + int send_ret = 0; + + while (sent != size) { + send_ret = send(fd, (char*)&cmd + sent, size - sent, MSG_NOSIGNAL); + if (send_ret == -1) { + _E("send error! (%d)", errno); + return -1; + } + + sent += send_ret; + _D("send(%d: ret: %d) : %d / %d", fd, send_ret, sent, size); + } + + return 0; +} + +static int __hydra_send_launch_candidate_request(int fd) { + SECURE_LOGD("Send launch cmd to hydra, fd: %d", fd); + return __hydra_send_request(fd, LAUNCH_CANDIDATE); +} + +static void __candidate_info_free(candidate_info_t* info) { + int i; + + if (info == nullptr) + return; + + if (info->argv) { + for (i = 0; i < info->argc; i++) + free(info->argv[i]); + + free(info->argv); + } + + free(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, + }; + char argbuf[LOADER_ARG_LEN]; + candidate_info_t* info; + + if (cpt == nullptr) + return -EINVAL; + + info = static_cast(calloc(1, sizeof(candidate_info_t))); + if (info == nullptr) { + _E("calloc() is failed"); + return -ENOMEM; + } + + info->argv = static_cast(calloc(LOADER_ARG_DUMMY + 1, sizeof(char*))); + if (info->argv == nullptr) { + _E("calloc() is failed"); + __candidate_info_free(info); + return -ENOMEM; + } + + memset(argbuf, ' ', LOADER_ARG_LEN); + argbuf[LOADER_ARG_LEN - 1] = '\0'; + info->argv[LOADER_ARG_DUMMY] = strdup(argbuf); + + snprintf(loader_id_str, sizeof(loader_id_str), "%d", cpt->loader_id); + snprintf(type_str, sizeof(type_str), "%d", cpt->type); + info->argv[LOADER_ARG_PATH] = strdup(cpt->loader_path); + info->argv[LOADER_ARG_TYPE] = strdup(type_str); + info->argv[LOADER_ARG_ID] = strdup(loader_id_str); + info->argv[LOADER_ARG_HYDRA] = strdup(cpt->is_hydra ? "1" : "0"); + info->argv[LOADER_ARG_EXTRA] = strdup(cpt->loader_extra); + + info->argc = LOADER_ARG_DUMMY + 1; + info->type = cpt->type; + info->loader_id = cpt->loader_id; + + *candidate_info = info; + return 0; +} + +static int __prepare_candidate_process(int type, int loader_id) { + candidate_process_context_t* cpt = __find_slot(type, loader_id); + candidate_info_t* info; + int ret; + + if (cpt == nullptr) + return -1; + + if (cpt->is_hydra && cpt->hydra_pid != HYDRA_NONE) + return __hydra_send_launch_candidate_request(cpt->hydra_fd); + + _D("prepare candidate process / type:%d", type); + ret = __candidate_info_create(cpt, &info); + if (ret < 0) + return ret; + + info->pid = __fork_app_process(__exec_loader_process, info->argv, + cpt->sched_priority); + if (info->pid == -1) { + _E("Failed to create a child process. type: %d", type); + __candidate_info_free(info); + return -1; + } + + _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."); + __candidate_info_free(info); + return -1; + } + + cpt->last_exec_time = time(nullptr); + if (cpt->is_hydra) { + cpt->hydra_pid = info->pid; + } else { + cpt->pid = info->pid; + __set_live_timer(cpt); + } + + _log_print("[CANDIDATE]", "pid(%7d) | type(%d) | loader(%s)", info->pid, + cpt->loader_id, cpt->loader_name); + _memory_monitor_reset_timer(); + __candidate_info_free(info); + return 0; +} + +static gboolean __handle_timeout_event(gpointer user_data) { + candidate_process_context_t* cpc; + + cpc = (candidate_process_context_t*)user_data; + cpc->timer = 0; + + if (cpc->pid != CANDIDATE_NONE) { + _W("Candidate(%d) process(%d) is running", cpc->type, cpc->pid); + return G_SOURCE_REMOVE; + } + + __sequencer_add_slot(cpc); + __sequencer_run(); + return G_SOURCE_REMOVE; +} + +static void __set_timer(candidate_process_context_t* cpc) { + if (cpc == nullptr || cpc->timer > 0) + return; + + if ((cpc->detection_method & static_cast(launchpad::LoaderMethod::Timeout)) && + cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) { + cpc->timer = g_timeout_add(cpc->timeout_val, __handle_timeout_event, cpc); + } +} + +static void __reset_slot(candidate_process_context_t* cpc) { + if (cpc == nullptr) + return; + + cpc->send_fd = -1; + cpc->prepared = false; + cpc->pid = CANDIDATE_NONE; + cpc->client_channel = nullptr; + cpc->timer = 0; + cpc->live_timer = 0; + cpc->on_boot_timer = 0; +} + +static void __dispose_candidate_process(candidate_process_context_t* cpc) { + if (!cpc) + return; + + _D("Dispose candidate process %d", cpc->type); + if (cpc->pid > 0) { + _D("kill process %d", cpc->pid); + __kill_process(cpc->pid); + } + if (cpc->live_timer > 0) + g_source_remove(cpc->live_timer); + if (cpc->client_channel) + _io_channel_destroy(cpc->client_channel); + if (cpc->timer > 0) + g_source_remove(cpc->timer); + if (cpc->send_fd > 0) + close(cpc->send_fd); + if (cpc->on_boot_timer > 0) + g_source_remove(cpc->on_boot_timer); + __reset_slot(cpc); +} + +static void __dispose_hydra_process(candidate_process_context_t* cpc) { + if (!cpc) + return; + + __dispose_candidate_process(cpc); + + _D("Dispose hydra process %d", cpc->type); + if (cpc->hydra_pid > 0) { + _D("kill process %d", cpc->hydra_pid); + __kill_process(cpc->hydra_pid); + cpc->hydra_pid = HYDRA_NONE; + } + + if (cpc->hydra_fd > 0) { + close(cpc->hydra_fd); + cpc->hydra_fd = -1; + } +} + +static int __send_launchpad_loader(candidate_process_context_t* cpc, + app_pkt_t* pkt, + const char* app_path, + int clifd) { + int pid = -1; + int ret; + + ret = _delete_sock_path(cpc->pid, getuid()); + if (ret != 0) + return -1; + + __candidate_process_real_launch(cpc->send_fd, pkt); + SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s", cpc->pid, + app_path); + + pid = cpc->pid; + cpc->pid = CANDIDATE_NONE; + __dispose_candidate_process(cpc); + __set_timer(cpc); + __update_slot_score(cpc); + + return pid; +} + +static int __normal_fork_exec(int argc, char** argv, const char* app_path) { + char* libdir; + char err_buf[1024]; + + _D("start real fork and exec"); + + libdir = _get_libdir(app_path); + if (libdir) { + setenv("LD_LIBRARY_PATH", libdir, 1); + free(libdir); + } + + _close_all_fds(); + + 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))); + return -1; + } + /* never reach*/ + 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(), + [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(); + }); + + 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); +} + +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; + } + + 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; + } + + 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; + } + + 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; + } + + new_argv = (char**)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 = 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; +} + +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) + putenv("TIZEN_DEBUGGING_PORT=1"); + + ret = __create_app_argv(&app_argc, &app_argv, app_path, kb, + menu_info->app_type); + if (ret < 0) { + _E("Failed to create app argv"); + exit(-1); + } + + for (i = 0; i < app_argc; i++) + SECURE_LOGD("input argument %d : %s##", i, app_argv[i]); + + PERF("setup argument done"); + __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) { + char* file_name; + const char* enabled_light_user; + char process_name[AUL_PR_NAME]; + int ret; + + /* Set new session ID & new process group ID*/ + /* In linux, child can set new session ID without check permission */ + /* TODO : should be add to check permission in the kernel*/ + setsid(); + + ret = _launchpad_plugin_prepare_app(appid, kb); + if (ret < 0) { + _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret); + return PAD_ERR_FAILED; + } + + ret = _enable_external_pkg(kb, menu_info->pkgid, + menu_info->global ? GLOBAL_USER : getuid()); + if (ret < 0) + return PAD_ERR_FAILED; + + if (menu_info->global) + ret = trust_anchor_launch(menu_info->pkgid, GLOBAL_USER); + else + ret = trust_anchor_launch(menu_info->pkgid, getuid()); + if (ret != TRUST_ANCHOR_ERROR_NONE && + ret != TRUST_ANCHOR_ERROR_NOT_INSTALLED) { + _E("trust_anchor_launch() returns %d", ret); + return PAD_ERR_REJECTED; + } + + ret = _mount_res_dir(menu_info->root_path, kb); + if (ret < 0) + return PAD_ERR_FAILED; + + if (bundle_get_type(kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) + _debug_change_mount_namespace(); + + /* SET PRIVILEGES*/ + enabled_light_user = bundle_get_val(kb, AUL_K_ENABLED_LIGHT_USER); + _W("security_manager_prepare_app2 ++ %s", appid); + ret = security_manager_prepare_app2(appid, enabled_light_user); + _W("security_manager_prepare_app2 -- %s", appid); + if (ret != SECURITY_MANAGER_SUCCESS) + return PAD_ERR_REJECTED; + + if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) + _setup_stdio(basename(app_path)); + + /* SET DUMPABLE - for coredump*/ + prctl(PR_SET_DUMPABLE, 1); + + /* SET PROCESS NAME*/ + if (app_path == nullptr) + return PAD_ERR_INVALID_ARGUMENT; + + file_name = const_cast(strrchr(app_path, '/')); + if (file_name == nullptr) + return PAD_ERR_INVALID_PATH; + + file_name++; + if (*file_name == '\0') + return PAD_ERR_INVALID_PATH; + + memset(process_name, '\0', AUL_PR_NAME); + snprintf(process_name, AUL_PR_NAME, "%s", file_name); + prctl(PR_SET_NAME, process_name); + + /* SET ENVIROMENT*/ + _set_env(menu_info, kb); + + ret = _wait_tep_mount(kb); + if (ret < 0) + return PAD_ERR_FAILED; + + if (bundle_get_type(kb, AUL_K_SDK) == BUNDLE_TYPE_NONE) { + ret = _prepare_app_socket(); + if (ret < 0) + return PAD_ERR_FAILED; + + ret = _prepare_id_file(); + if (ret < 0) + return PAD_ERR_FAILED; + } + + _send_cmd_to_amd(APP_STARTUP_SIGNAL); + return 0; +} + +static int __exec_app_process(void* arg) { + auto* launch_arg = static_cast(arg); + int ret; + + _print_hwc_log("%d|after calling fork(). %s", getpid(), launch_arg->appid); + 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); + + _signal_unblock_sigchld(); + + _delete_sock_path(getpid(), getuid()); + + PERF("prepare exec - first done"); + ret = __prepare_exec(launch_arg->appid, launch_arg->app_path, + launch_arg->menu_info, launch_arg->kb); + if (ret < 0) + return ret; + + PERF("prepare exec - second done"); + __real_launch(launch_arg->app_path, launch_arg->kb, launch_arg->menu_info); + + 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) { + struct app_launch_arg arg; + int pid; + + arg.appid = appid; + arg.app_path = app_path; + arg.menu_info = menu_info; + arg.kb = kb; + + _print_hwc_log("before calling fork(). %s", appid); + pid = __fork_app_process(__exec_app_process, &arg, 0); + if (pid <= 0) + _E("failed to fork app process"); + + SECURE_LOGD("==> real launch pid : %d %s", pid, app_path); + + return pid; +} + +static int __create_sock_activation(void) { + int fds; + char launchpad_process_pool_sock_path[108]; + int i; + + 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); + + 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, + 0) > 0) + return i; + } + + _W("There is no socket stream"); + return -1; +} + +static int __get_launchpad_listen_fd(void) { + const char* val; + + val = getenv("LAUNCHPAD_LISTEN_FD"); + if (!val) { + _E("Failed to get LAUNCHPAD_LISTEN_FD"); + return -1; + } + + _W("Listen Fd: %s", val); + return atoi(val); +} + +static int __launchpad_pre_init(int argc, char** argv) { + int fd; + + /* create launchpad sock */ + fd = __create_sock_activation(); + if (fd >= 0) + return fd; + + fd = __get_launchpad_listen_fd(); + if (fd >= 0) + return fd; + + fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_SOCK); + if (fd < 0) { + _E("server sock error %d", fd); + return -1; + } + + return fd; +} + +static bool __handle_loader_client_event(int fd, + io_condition_e cond, + void* data) { + auto* cpc = static_cast(data); + + if (cpc == nullptr) + return false; + + if (cond & (IO_HUP | IO_NVAL)) { + SECURE_LOGE( + "Type %d candidate process was " + "(POLLHUP|POLLNVAL), pid: %d", + cpc->type, cpc->pid); + cpc->pid = CANDIDATE_NONE; + __dispose_candidate_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + return false; + } + + return true; +} + +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; + + if (cpc == nullptr) + return false; + + if (cond & (IO_HUP | IO_NVAL)) { + SECURE_LOGE( + "Type %d hydra process was " + "(POLLHUP|POLLNVAL), pid: %d", + cpc->type, cpc->hydra_pid); + __dispose_hydra_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + return false; + } + + if (cond & IO_IN) { + ret = recv(cpc->hydra_fd, &recv_pid, sizeof(recv_pid), MSG_WAITALL); + if (ret == -1) { + _E("recv() is failed. errno(%d)", errno); + } else { + _W("candidate process: %d", recv_pid); + if (recv_pid > 1) + cpc->pid = recv_pid; + } + } + + return true; +} + +static bool __handle_loader_event(int fd, io_condition_e cond, void* data) { + auto* cpc = static_cast(data); + int client_fd; + int client_pid; + int ret; + + if (cpc == nullptr) + return false; + + if (!cpc->prepared) { + ret = __accept_candidate_process(fd, &client_fd, &client_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 */ + if (cpc->is_hydra) + cpc->pid = client_pid; + + cpc->prepared = true; + cpc->send_fd = client_fd; + + SECURE_LOGI( + "Type %d candidate process was connected, " + "pid: %d", + cpc->type, cpc->pid); + + _print_hwc_log( + "Type %d candidate process was connected, " + "pid: %d", + cpc->type, cpc->pid); + cpc->client_channel = _io_channel_create( + client_fd, static_cast(IO_IN | IO_HUP), + __handle_loader_client_event, cpc); + if (!cpc->client_channel) + close(client_fd); + } + } else { + __refuse_candidate_process(fd); + _E("Refused candidate process connection"); + } + + return true; +} + +static bool __handle_hydra_event(int fd, io_condition_e cond, void* data) { + auto* cpc = static_cast(data); + int client_fd; + int client_pid; + int ret; + + if (cpc == nullptr) + return false; + + if (!cpc->prepared) { + ret = + __accept_candidate_process(fd, &client_fd, &client_pid, cpc->hydra_pid); + if (ret >= 0) { + cpc->hydra_fd = client_fd; + + SECURE_LOGD( + "Type %d hydra process was connected," + " pid: %d", + cpc->type, cpc->hydra_pid); + + cpc->client_channel = _io_channel_create( + client_fd, static_cast(IO_IN | IO_HUP), + __handle_hydra_client_event, cpc); + if (!cpc->client_channel) + close(client_fd); + } + } else { + __refuse_candidate_process(fd); + _E("Refused hydra process connection"); + } + + 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( + 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() --"); + } + + g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid)); + } + + _log_print("[SIGCHLD]", "pid(%7d)", pid); + cpc = __find_slot_from_pid(pid); + if (cpc != nullptr) { + cpc->pid = CANDIDATE_NONE; + __dispose_candidate_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + } else { + cpc = __find_hydra_slot_from_pid(pid); + if (cpc != nullptr) { + cpc->hydra_pid = HYDRA_NONE; + __dispose_hydra_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + } + } + + cpc = __find_slot_from_caller_pid(pid); + while (cpc) { + __remove_slot(static_cast(launchpad::LoaderType::Dynamic), cpc->loader_id); + cpc = __find_slot_from_caller_pid(pid); + } +} + +static bool __handle_label_monitor(int fd, io_condition_e cond, void* data) { + candidate_process_context_t* cpc; + GList* iter = candidate_slot_list; + + if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { + _E("fd(%d), io_condition(%d)", fd, cond); + abort(); + return false; + } + + _D("fd(%d) condition(%d)", fd, cond); + _log_print("[LABEL]", "fd(%d), condition(%d)", fd, cond); + security_manager_app_labels_monitor_process(label_monitor); + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (cpc->is_hydra) { + if (cpc->hydra_pid > 0) { + __dispose_hydra_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + } + } else if (cpc->pid > 0) { + __dispose_candidate_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + } + + iter = g_list_next(iter); + } + + return true; +} + +static float __interpolator(float input, int cpu_max, int cpu_min) { + float ret; + float min = cpu_min / 100.0f; + float max = cpu_max / 100.0f; + + if (input > 1.0f) + input = 1.0f; + if (input < 0.0f) + input = 0.0f; + + ret = cos(input * PI) / 2.0f + 0.5f; + ret *= max - min; + ret += min; + + return ret; +} + +static void __update_threshold(candidate_process_context_t* cpc, float delta) { + static float pos = 0.0f; + + pos += delta; + if (pos < 0.0f) + pos = 0.0f; + + 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); +} + +static gboolean __handle_idle_checker(gpointer data) { + unsigned long long total = 0; + unsigned long long idle = 0; + int per; + candidate_process_context_t* cpc; + + if (!data) { + _E("Critical error!"); + __sequencer.idle_checker = 0; + __sequencer.running_cpc = nullptr; + return G_SOURCE_REMOVE; + } + + cpc = (candidate_process_context_t*)data; + if (cpc->app_check && !cpc->app_exists) { + _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; + } + + if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) { + _W("Slot state is not running. loader(%s:%d)", cpc->loader_name, cpc->type); + __sequencer.idle_checker = 0; + __sequencer.running_cpc = nullptr; + return G_SOURCE_REMOVE; + } + + if (cpc->pid != CANDIDATE_NONE) { + _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; + } + + _get_cpu_idle(&total, &idle); + if (total == cpc->cpu_total_time) + total++; + + per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time); + _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type); + + if (per >= cpc->threshold) { + __update_threshold(cpc, -0.02f * (per - cpc->threshold)); + __prepare_candidate_process(cpc->type, cpc->loader_id); + cpc->touched = true; + __sequencer.idle_checker = 0; + __sequencer.running_cpc = nullptr; + return G_SOURCE_REMOVE; + } + + cpc->cpu_idle_time = idle; + cpc->cpu_total_time = total; + __update_threshold(cpc, 0.05f); + + 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); + __sequencer.idle_checker = 0; + __sequencer.running_cpc = nullptr; + __sequencer_add_slot(cpc); + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; +} + +static gboolean __on_boot_timeout_cb(gpointer user_data) { + auto* context = static_cast(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); + } else { + __prepare_candidate_process(context->type, context->loader_id); + context->touched = true; + } + + return G_SOURCE_REMOVE; +} + +static void __add_on_boot_timer(candidate_process_context_t* context) { + if (context->on_boot_timer != 0) + return; + + context->on_boot_timer = + g_timeout_add(context->on_boot_timeout, __on_boot_timeout_cb, context); +} + +static int __add_idle_checker(int detection_method, GList* cur) { + candidate_process_context_t* cpc; + GList* iter = cur; + + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + if (!cpc->touched && cpc->on_boot && cpc->on_boot_timeout > 0) + __add_on_boot_timer(cpc); + + if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) { + iter = g_list_next(iter); + continue; + } + + if (strcmp("null", cpc->loader_path) == 0) { + iter = g_list_next(iter); + continue; + } + + if (!cpc->touched && !cpc->on_boot) { + iter = g_list_next(iter); + continue; + } + + if (cpc->app_check && !cpc->app_exists) { + iter = g_list_next(iter); + continue; + } + + if (cpc->pid == CANDIDATE_NONE && + (!cpc->touched || (cpc->detection_method & detection_method))) { + if (cpc->timer > 0) { + g_source_remove(cpc->timer); + cpc->timer = 0; + } + + cpc->cur_event = detection_method; + __sequencer_add_slot(cpc); + __sequencer_run(); + } + + iter = g_list_next(iter); + } + + return -1; +} + +static int __dispatch_cmd_hint(bundle* kb, int detection_method) { + _W("cmd hint %d", detection_method); + __add_idle_checker(detection_method, candidate_slot_list); + + return 0; +} + +static int __dispatch_cmd_add_loader(bundle* kb) { + const char* add_slot_str = nullptr; + const char* caller_pid = nullptr; + const char* extra; + int lid, size; + char* loader_name; + candidate_process_context_t* cpc; + slot_info_t slot_info; + + _W("cmd add loader"); + add_slot_str = bundle_get_val(kb, AUL_K_LOADER_PATH); + caller_pid = bundle_get_val(kb, AUL_K_CALLER_PID); + extra = bundle_get_val(kb, AUL_K_LOADER_EXTRA); + + if (add_slot_str == nullptr || caller_pid == nullptr) + return -1; + + lid = __make_loader_id(); + size = snprintf(0, 0, "%s%s%d", add_slot_str, caller_pid, lid); + loader_name = (char*)malloc(size + 1); + if (loader_name == nullptr) { + _E("Out of memory"); + return -1; + } + + snprintf(loader_name, size, "%s%s%d", add_slot_str, caller_pid, lid); + + slot_info.type = static_cast(launchpad::LoaderType::Dynamic); + slot_info.loader_id = lid; + slot_info.caller_pid = atoi(caller_pid); + slot_info.loader_name = loader_name; + slot_info.loader_path = add_slot_str; + slot_info.loader_extra = extra; + slot_info.detection_method = static_cast( + launchpad::LoaderMethod::Timeout | launchpad::LoaderMethod::Visibility); + slot_info.activation_method = + static_cast(launchpad::LoaderMethod::Request | + launchpad::LoaderMethod::AvailableMemory); + slot_info.deactivation_method = static_cast( + launchpad::LoaderMethod::Ttl | launchpad::LoaderMethod::OutOfMemory); + slot_info.ttl = 600; + slot_info.timeout_val = 2000; + slot_info.threshold_max = launchpad::DefaultCpuThresholdMax; + slot_info.threshold_min = launchpad::DefaultCpuThresholdMin; + slot_info.on_boot = false; + slot_info.app_exists = true; + slot_info.is_hydra = false; + slot_info.app_check = true; + slot_info.on_boot_timeout = 0; + slot_info.sched_priority = 0; + + cpc = __add_slot(&slot_info); + free(loader_name); + if (cpc == nullptr) + return -1; + + __set_timer(cpc); + return lid; +} + +static int __dispatch_cmd_add_app_defined_loader(bundle* kb) { + const char* loader_name; + int lid, len; + candidate_process_context_t* cpc; + launchpad::LoaderInfoPtr info; + bundle_raw* extra; + slot_info_t slot_info; + + _W("cmd add defined loader"); + loader_name = bundle_get_val(kb, AUL_K_LOADER_NAME); + + if (loader_name == nullptr) { + _E("loader_name is nullptr"); + return -EINVAL; + } + + info = app_defined_loader_info_manager->FindLoaderInfo(loader_name); + if (info == nullptr) { + _E("loader_name %s, info %d", loader_name, info != nullptr); + return -EINVAL; + } + + cpc = __find_slot_from_loader_name(loader_name); + if (cpc == nullptr) { + lid = __make_loader_id(); + bundle_encode(info->GetExtra().GetHandle(), &extra, &len); + slot_info.type = static_cast(launchpad::LoaderType::Dynamic); + slot_info.loader_id = lid; + slot_info.caller_pid = 0; + 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.ttl = info->GetTtl(); + slot_info.timeout_val = 2000; + slot_info.threshold_max = launchpad::DefaultCpuThresholdMax; + slot_info.threshold_min = launchpad::DefaultCpuThresholdMin; + slot_info.on_boot = false; + slot_info.app_exists = true; + slot_info.is_hydra = false; + slot_info.app_check = true; + slot_info.on_boot_timeout = 0; + slot_info.sched_priority = 0; + + cpc = __add_slot(&slot_info); + bundle_free_encoded_rawdata(&extra); + if (cpc == nullptr) { + _E("cpc is nullptr"); + return -ENOMEM; + } + } else { + lid = cpc->loader_id; + } + + if (cpc->pid == CANDIDATE_NONE) + __prepare_candidate_process(static_cast(launchpad::LoaderType::Dynamic), lid); + + return lid; +} + +static int __dispatch_cmd_remove_loader(bundle* kb) { + const char* id = bundle_get_val(kb, AUL_K_LOADER_ID); + int lid; + + _W("cmd remove loader"); + if (id) { + lid = atoi(id); + if (__remove_slot(static_cast(launchpad::LoaderType::Dynamic), lid) == 0) + return 0; + } + + return -1; +} + +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) + return -1; + + if (strcmp(buf, "User") == 0 || strcmp(buf, "System") == 0 || + strcmp(buf, "System::Privileged") == 0) + return 0; + + return -1; +} + +static bool __is_hw_acc(const char* hwacc) { + if (strcmp(hwacc, "USE") == 0 || + (strcmp(hwacc, "SYS") == 0 && __sys_hwacc == SETTING_HW_ACCELERATION_ON)) + return true; + + return false; +} + +static candidate_process_context_t* __find_available_slot( + const char* hwacc, + const char* app_type, + const char* loader_name, + candidate_process_context_t** org_cpc) { + launchpad::LoaderType type = launchpad::LoaderType::Unsupported; + candidate_process_context_t* cpc; + + if (loader_name) { + for (auto& info : loader_info_manager->GetLoaderInfoList()) { + if (info->GetName() == loader_name) { + type = info->GetType(); + break; + } + } + } else { + if (__is_hw_acc(hwacc)) + type = loader_info_manager->FindHwType(app_type); + else + type = loader_info_manager->FindSwType(app_type); + } + + cpc = __find_slot(static_cast(type), PAD_LOADER_ID_STATIC); + if (!cpc) + return nullptr; + + *org_cpc = cpc; + + if (cpc->prepared) + return cpc; + + auto a_types = loader_info_manager->GetAlternativeTypes(type); + if (a_types.empty()) + return nullptr; + + for (auto& a_type : a_types) { + cpc = __find_slot(static_cast(a_type), PAD_LOADER_ID_STATIC); + if (!cpc) + continue; + if (cpc->prepared) { + return cpc; + } + } + + return nullptr; +} + +static void __update_slot(int type, bool app_exists) { + candidate_process_context_t* cpc; + + cpc = __find_slot(type, PAD_LOADER_ID_STATIC); + if (!cpc) + return; + + cpc->app_exists = app_exists; + if (cpc->app_check && !cpc->app_exists) { + if (cpc->pid > 0) + __dispose_candidate_process(cpc); + __sequencer_remove_slot(cpc); + if (__sequencer_queue_is_empty()) + __sequencer_stop(); + } else { + if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) + return; + + if (!cpc->touched && !cpc->on_boot) + return; + + if (cpc->timer > 0) { + g_source_remove(cpc->timer); + cpc->timer = 0; + } + + if (cpc->pid == CANDIDATE_NONE) { + __sequencer_add_slot(cpc); + __sequencer_run(); + } + } +} + +static void __foreach_loader_info(const launchpad::LoaderInfoPtr& info, + void* data) { + struct app_info* ai = (struct app_info*)data; + auto it = std::find_if( + info->GetAppTypes().begin(), info->GetAppTypes().end(), + [&](const std::string& type) -> bool { return type == ai->type; }); + + if (it == info->GetAppTypes().end()) + return; + + info->SetAppExists(ai->exists); + __update_slot(static_cast(info->GetType()), info->IsAppExists()); +} + +static int __dispatch_cmd_update_app_type(bundle* b) { + int r; + struct app_info info; + const char* is_installed; + + info.type = bundle_get_val(b, AUL_K_APP_TYPE); + if (!info.type) + return -1; + + is_installed = bundle_get_val(b, AUL_K_IS_INSTALLED); + if (is_installed && !strcmp(is_installed, "true")) + info.exists = true; + else + info.exists = false; + + _I("[LAUNCHPAD] type(%s), exists(%d)", info.type, info.exists); + + for (auto& linfo : loader_info_manager->GetLoaderInfoList()) { + __foreach_loader_info(linfo, &info); + } + + return 0; +} + +static void __deactivate_slot(candidate_process_context_t* cpc) { + if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED) + return; + + cpc->state = CANDIDATE_PROCESS_STATE_PAUSED; + if (cpc->is_hydra) + __dispose_hydra_process(cpc); + else + __dispose_candidate_process(cpc); +} + +static void __activate_slot(candidate_process_context_t* cpc) { + if (cpc->state == CANDIDATE_PROCESS_STATE_RUNNING) + return; + + cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; + if (!cpc->touched && !cpc->on_boot) + return; + + if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE) + return; + + if (cpc->detection_method & static_cast(launchpad::LoaderMethod::Timeout)) + __set_timer(cpc); +} + +static void __update_slot_state(candidate_process_context_t* cpc, + launchpad::LoaderMethod method, + bool force) { + switch (method) { + case launchpad::LoaderMethod::OutOfMemory: + if ((force || cpc->deactivation_method & static_cast(method)) && __is_low_memory()) { + _W("Low memory, deactivate slot %d", cpc->type); + __deactivate_slot(cpc); + } else { + __activate_slot(cpc); + } + break; + case launchpad::LoaderMethod::Ttl: + if (force || cpc->deactivation_method & static_cast(method)) + __deactivate_slot(cpc); + break; + case launchpad::LoaderMethod::AvailableMemory: + if (force || cpc->activation_method & static_cast(method)) + __activate_slot(cpc); + break; + case launchpad::LoaderMethod::Request: + if (force || cpc->activation_method & static_cast(method)) + __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, force); + break; + default: + __activate_slot(cpc); + break; + } +} + +static void __request_destroy(request_t* request) { + if (request == nullptr) + return; + + if (request->clifd > -1) + close(request->clifd); + if (request->menu_info) + _appinfo_free(request->menu_info); + if (request->kb) + bundle_free(request->kb); + if (request->pkt) + free(request->pkt); + free(request); +} + +static int __request_create(int fd, request_t** request) { + struct ucred cr; + request_t* req; + + if (request == nullptr) { + _E("Invalid parameter"); + return -EINVAL; + } + + req = static_cast(calloc(1, sizeof(request_t))); + if (req == nullptr) { + _E("calloc() is failed"); + return -ENOMEM; + } + + req->clifd = -1; + req->pkt = _accept_recv_pkt_raw(fd, &req->clifd, &cr); + if (req->pkt == nullptr) { + _E("_accept_recv_pkt_raw() is failed"); + __request_destroy(req); + return -ECOMM; + } + + req->kb = bundle_decode(req->pkt->data, req->pkt->len); + if (req->kb == nullptr) { + _E("bundle_decode() is failed"); + __real_send(req->clifd, -EINVAL); + req->clifd = -1; + __request_destroy(req); + return -EINVAL; + } + + req->cmd = req->pkt->cmd; + req->caller_pid = cr.pid; + req->caller_uid = cr.uid; + *request = req; + return 0; +} + +static void __request_send_result(request_h request, int result) { + if (request->clifd < 0) + return; + + __real_send(request->clifd, result); + request->clifd = -1; +} + +static int __visibility_request_handler(request_h request) { + int ret = __dispatch_cmd_hint(request->kb, + static_cast(launchpad::LoaderMethod::Visibility)); + + __request_send_result(request, ret); + _D("[PAD_CMD_VISIBILITY] result: %d", ret); + return ret; +} + +static int __add_loader_request_handler(request_h request) { + int ret = __dispatch_cmd_add_loader(request->kb); + + __request_send_result(request, ret); + _D("[PAD_CMD_ADD_LOADER] result: %d", ret); + return ret; +} + +static int __remove_loader_request_handler(request_h request) { + int ret = __dispatch_cmd_remove_loader(request->kb); + + __request_send_result(request, ret); + _D("[PAD_CMD_REMOVE_LOADER] result: %d", ret); + return ret; +} + +static int __make_default_slots_request_handler(request_h request) { + int ret = __add_default_slots(); + + __request_send_result(request, ret); + _D("[PAD_CMD_MAKE_DEFAULT_SLOTS] result: %d", ret); + return ret; +} + +static int __prepare_app_defined_loader_request_handler(request_h request) { + int ret = __dispatch_cmd_add_app_defined_loader(request->kb); + + __request_send_result(request, ret); + _D("[PAD_CMD_PREPARE_APP_DEFINED_LOADER] result: %d", ret); + return ret; +} + +static int __demand_request_handler(request_h request) { + int ret = __dispatch_cmd_hint(request->kb, + static_cast(launchpad::LoaderMethod::Demand)); + + __request_send_result(request, ret); + _D("[PAD_CMD_DEMAND] result: %d", ret); + return ret; +} + +static int __ping_request_handler(request_h request) { + __request_send_result(request, getpid()); + _D("[PAD_CMD_PING] result: %d", getpid()); + return 0; +} + +static int __update_app_type_request_handler(request_h request) { + int ret = __dispatch_cmd_update_app_type(request->kb); + + _D("[PAD_CMD_UPDATE_APP_TYPE] result: %d", ret); + return ret; +} + +static int __connect_request_handler(request_h request) { + if (__client_fd != -1) + close(__client_fd); + + __client_fd = request->clifd; + request->clifd = -1; + _D("[PAD_CMD_CONNECT] client fd: %d", __client_fd); + return 0; +} + +static int __launch_request_prepare(request_h request) { + const appinfo_t* menu_info; + int type = -1; + + request->menu_info = _appinfo_create(request->kb); + if (request->menu_info == nullptr) { + _E("_appinfo_create() is failed"); + return -1; + } + + request->app_path = _appinfo_get_app_path(request->menu_info); + if (request->app_path == nullptr) { + _E("_appinfo_get_app_path() is failed"); + return -1; + } + + if (request->app_path[0] != '/') { + _E("app path is not absolute path"); + return -1; + } + + menu_info = request->menu_info; + if (menu_info->hwacc == nullptr) { + _E("Failed to find HW acceeleration type"); + return -1; + } + + SECURE_LOGD("appid: %s", menu_info->appid); + SECURE_LOGD("exec: %s", menu_info->app_path); + SECURE_LOGD("comp_type: %s", menu_info->comp_type); + SECURE_LOGD("internal pool: %s", menu_info->internal_pool); + SECURE_LOGD("hwacc: %s", menu_info->hwacc); + SECURE_LOGD("app_type: %s", menu_info->app_type); + SECURE_LOGD("pkg_type: %s", menu_info->pkg_type); + + if (menu_info->comp_type && !strcmp(menu_info->comp_type, "svcapp")) { + request->loader_id = __get_loader_id(request->kb); + if (request->loader_id > PAD_LOADER_ID_DYNAMIC_BASE) { + type = static_cast(launchpad::LoaderType::Dynamic); + request->cpc = __find_slot(type, request->loader_id); + if (request->cpc && !request->cpc->prepared) + request->cpc = nullptr; + } else { + 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")) { + request->loader_id = PAD_LOADER_ID_DIRECT; + } else { + request->loader_id = __get_loader_id(request->kb); + if (request->loader_id <= PAD_LOADER_ID_STATIC) { + request->cpc = + __find_available_slot(menu_info->hwacc, menu_info->app_type, + menu_info->loader_name, &request->org_cpc); + } else { + type = static_cast(launchpad::LoaderType::Dynamic); + request->cpc = __find_slot(type, request->loader_id); + if (request->cpc && !request->cpc->prepared) + request->cpc = nullptr; + } + } + + _modify_bundle(request->kb, request->caller_pid, request->menu_info, + request->cmd); + if (menu_info->appid == nullptr) { + _E("Unable to get appid from app info"); + return -1; + } + + PERF("Getting package information & modifying bundle done"); + return 0; +} + +static void __launch_request_complete(request_h request) { + _memory_monitor_reset_timer(); + __request_send_result(request, request->pid); + + if (request->pid > 0) { + _dbus_send_app_launch_signal(request->pid, request->menu_info->appid); + g_hash_table_insert(__pid_table, GINT_TO_POINTER(request->pid), + strdup(request->menu_info->appid)); + _log_print("[LAUNCH]", "pid(%7d) | appid(%s)", request->pid, + request->menu_info->appid); + } +} + +static void __handle_direct_launch(request_h request) { + if (request->org_cpc && + (!request->org_cpc->app_check || request->org_cpc->app_exists) && + request->org_cpc->pid == CANDIDATE_NONE && + !__sequencer_slot_exist(request->org_cpc)) { + if (request->org_cpc->timer > 0) { + g_source_remove(request->org_cpc->timer); + request->org_cpc->timer = 0; + } + + __update_slot_state(request->org_cpc, launchpad::LoaderMethod::Request, true); + __set_timer(request->org_cpc); + } +} + +static void __fork_processing(request_h request) { + if (bundle_get_type(request->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) + _debug_init(); + + _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); + if (request->pid == -1) { + _E("Failed to create a child process. appid(%s)", + request->menu_info->appid); + } + + __request_send_result(request, request->pid); + _W("appid: %s, pid: %d", request->menu_info->appid, request->pid); + __handle_direct_launch(request); +} + +static int __launch_request_do(request_h request) { + if (request->loader_id == PAD_LOADER_ID_DIRECT || request->cpc == nullptr) { + __fork_processing(request); + return 0; + } + + _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); + return 0; +} + +static int __launch_request_handler(request_h request) { + int ret; + + traceBegin(TTRACE_TAG_APPLICATION_MANAGER, "LAUNCHPAD:LAUNCH"); + INIT_PERF(kb); + PERF("Packet processing start"); + + ret = __launch_request_prepare(request); + if (ret < 0) { + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + __request_send_result(request, ret); + return ret; + } + + ret = __launch_request_do(request); + if (ret < 0) + request->pid = ret; + + __launch_request_complete(request); + traceEnd(TTRACE_TAG_APPLICATION_MANAGER); + _D("[PAD_CMD_LAUNCH] appid: %s, result: %d", request->menu_info->appid, + request->pid); + return 0; +} + +static request_handler __request_handlers[PAD_CMD_CONNECT + 1] = {}; + +static bool __handle_launch_event(int fd, io_condition_e cond, void* data) { + request_t* request = nullptr; + int ret; + + if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { + _E("fd(%d), condition(%d)", fd, cond); + g_idle_add(__launchpad_recovery_cb, __launchpad_channel); + __launchpad_channel = nullptr; + return false; + } + + ret = __request_create(fd, &request); + if (ret != 0) + return true; + + _W("cmd(%d), caller(%d)", request->cmd, request->caller_pid); + if (request->caller_uid >= REGULAR_UID_MIN) { + if (__check_caller_by_pid(request->caller_pid) < 0) { + _E("Permission denied. pid(%d)", request->caller_pid); + __request_send_result(request, -EPERM); + __request_destroy(request); + return true; + } + } + + if (request->cmd < 0 || request->cmd >= ARRAY_SIZE(__request_handlers) || + __request_handlers[request->cmd] == nullptr) { + _E("Unknown command: %d", request->cmd); + __request_send_result(request, -EINVAL); + __request_destroy(request); + return true; + } + + __request_handlers[request->cmd](request); + __request_destroy(request); + return true; +} + +static void __destroy_slot(candidate_process_context_t* cpc) { + if (!cpc) + return; + + if (cpc->hydra_channel) + _io_channel_destroy(cpc->hydra_channel); + + if (cpc->channel) + _io_channel_destroy(cpc->channel); + + if (cpc->loader_extra) + free(cpc->loader_extra); + + if (cpc->loader_path) + free(cpc->loader_path); + + if (cpc->loader_name) + free(cpc->loader_name); + + free(cpc); +} + +static candidate_process_context_t* __create_slot(slot_info_t* info) { + candidate_process_context_t* cpc; + + cpc = static_cast( + calloc(1, sizeof(candidate_process_context_t))); + if (cpc == nullptr) { + _E("Out of memory"); + return nullptr; + } + + cpc->loader_name = strdup(info->loader_name); + if (cpc->loader_name == nullptr) { + _E("Failed to duplicate loader name(%s)", info->loader_name); + __destroy_slot(cpc); + return nullptr; + } + + cpc->loader_path = strdup(info->loader_path); + if (cpc->loader_path == nullptr) { + _E("Failed to duplicate loader path(%s)", info->loader_path); + __destroy_slot(cpc); + return nullptr; + } + + cpc->loader_extra = + info->loader_extra ? strdup(info->loader_extra) : strdup(""); + if (cpc->loader_extra == nullptr) { + _E("Failed to duplicate loader extra(%s)", info->loader_extra); + __destroy_slot(cpc); + return nullptr; + } + + cpc->type = info->type; + cpc->prepared = false; + cpc->pid = CANDIDATE_NONE; + cpc->hydra_pid = HYDRA_NONE; + cpc->caller_pid = info->caller_pid; + cpc->loader_id = info->loader_id; + cpc->send_fd = -1; + cpc->hydra_fd = -1; + cpc->last_exec_time = 0; + cpc->timer = 0; + cpc->detection_method = info->detection_method; + cpc->timeout_val = info->timeout_val; + cpc->cpu_total_time = 0; + cpc->cpu_idle_time = 0; + cpc->threshold = info->threshold_max; + cpc->threshold_max = info->threshold_max; + cpc->threshold_min = info->threshold_min; + cpc->on_boot = info->on_boot; + cpc->app_exists = info->app_exists; + cpc->touched = false; + cpc->cur_event = 0; + cpc->activation_method = info->activation_method; + cpc->deactivation_method = info->deactivation_method; + cpc->ttl = info->ttl; + cpc->live_timer = 0; + cpc->is_hydra = info->is_hydra; + cpc->app_check = info->app_check; + cpc->score = WIN_SCORE; + cpc->pss = 0; + cpc->cpu_check_count = 0; + cpc->on_boot_timeout = info->on_boot_timeout; + cpc->sched_priority = info->sched_priority; + + 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); + return cpc; +} + +static candidate_process_context_t* __add_slot(slot_info_t* info) { + candidate_process_context_t* cpc; + int fd; + io_channel_h channel; + int hydra_fd; + io_channel_h hydra_channel; + + if (info == nullptr) + return nullptr; + + if (__find_slot(info->type, info->loader_id) != nullptr) + return nullptr; + + cpc = __create_slot(info); + if (cpc == nullptr) + return nullptr; + + 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); + __destroy_slot(cpc); + return nullptr; + } + + channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc); + if (!channel) { + close(fd); + __destroy_slot(cpc); + return nullptr; + } + + cpc->channel = channel; + + 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); + __destroy_slot(cpc); + return nullptr; + } + + hydra_channel = + _io_channel_create(hydra_fd, IO_IN, __handle_hydra_event, cpc); + if (!hydra_channel) { + close(hydra_fd); + __destroy_slot(cpc); + return nullptr; + } + + cpc->hydra_channel = hydra_channel; + } + + candidate_slot_list = g_list_append(candidate_slot_list, cpc); + + return cpc; +} + +static int __remove_slot(int type, int loader_id) { + candidate_process_context_t* cpc; + GList* iter; + + iter = candidate_slot_list; + while (iter) { + cpc = (candidate_process_context_t*)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); + __destroy_slot(cpc); + return 0; + } + + iter = g_list_next(iter); + } + + return -1; +} + +static int __init_launchpad_fd(int argc, char** argv) { + int fd; + + fd = __launchpad_pre_init(argc, argv); + if (fd < 0) { + _E("launchpad pre init failed"); + return -1; + } + + auto cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL; + __launchpad_channel = _io_channel_create( + fd, static_cast(cond), __handle_launch_event, nullptr); + if (!__launchpad_channel) { + close(fd); + return -1; + } + + return 0; +} + +static bool __on_directory_create(const char* event_name, + uint32_t mask, + void* user_data) { + if (!event_name) { + _E("Invalid parameter"); + return true; + } + + if (!strcmp(event_name, LOADERS_PATH)) { + _W("%s is created", LOADERS_PATH); + __init_app_defined_loader_monitor(); + return false; + } + + return true; +} + +static bool __on_file_change(const char* event_name, + uint32_t mask, + void* user_data) { + char buf[PATH_MAX]; + char* ext; + launchpad::LoaderInfoPtr info; + candidate_process_context_t* cpc; + + if (!event_name) { + _E("Invalid parameter"); + return true; + } + + ext = const_cast(strrchr(event_name, '.')); + if (ext == nullptr || strcmp(ext, ".loader") != 0) + return true; + + _W("event_name(%s), mask(%u)", event_name, mask); + if (mask & IN_CREATE) { + app_defined_loader_info_manager->LoadFile(event_name); + } else if (mask & IN_DELETE) { + snprintf(buf, ext - event_name + 1, "%s", event_name); + + info = app_defined_loader_info_manager->FindLoaderInfo(buf); + cpc = __find_slot_from_loader_name(info->GetName().c_str()); + __remove_slot(cpc->type, cpc->loader_id); + app_defined_loader_info_manager->Unload(buf); + } + + return true; +} + +static void __init_app_defined_loader_monitor(void) { + int ret; + + ret = access(APP_DEFINED_LOADER_INFO_PATH, F_OK); + 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); + if (ret != 0) + _E("Failed to add inotify watch %s", OPT_SHARE_PATH); + + return; + } + + ret = _inotify_add_watch(APP_DEFINED_LOADER_INFO_PATH, IN_CREATE | IN_DELETE, + __on_file_change, nullptr); + + if (ret < 0) { + _E("Failed to add inotify watch %s", APP_DEFINED_LOADER_INFO_PATH); + } + + return; +} + +static int __init_label_monitor_fd(void) { + int r; + int fd = -1; + + auto err_handler = [&]() -> int { + if (fd > 0) + close(fd); + + if (label_monitor) { + security_manager_app_labels_monitor_finish(label_monitor); + label_monitor = nullptr; + } + return -1; + }; + + r = security_manager_app_labels_monitor_init(&label_monitor); + if (r != SECURITY_MANAGER_SUCCESS) + return -1; + + r = security_manager_app_labels_monitor_process(label_monitor); + if (r != SECURITY_MANAGER_SUCCESS) + return err_handler(); + + security_manager_app_labels_monitor_get_fd(label_monitor, &fd); + if (fd < 0) { + _E("failed to get fd"); + return err_handler(); + } + + auto cond = IO_IN | IO_PRI | IO_HUP | IO_ERR | IO_NVAL; + __label_monitor_channel = _io_channel_create( + fd, static_cast(cond), __handle_label_monitor, nullptr); + if (!__label_monitor_channel) + return err_handler(); + + return 0; + + +} + +static int __verify_loader_caps(const char* loader) { + cap_t cap_d; + cap_flag_value_t eff_state; + cap_flag_value_t inh_state; + cap_value_t values[] = {CAP_SETGID, CAP_MAC_ADMIN}; + int r; + int i; + int size = ARRAY_SIZE(values); + + /* If Dytransition feature is enabled, CAP_MAC_ADMIN is unnecessary */ + if (label_monitor) + size--; + + cap_d = cap_get_file(loader); + if (!cap_d) { + _E("Failed to get cap from file(%s)", loader); + return -1; + } + + for (i = 0; i < size; i++) { + r = cap_get_flag(cap_d, values[i], CAP_INHERITABLE, &inh_state); + if (r != 0) { + _E("Failed to get cap inh - errno(%d)", errno); + cap_free(cap_d); + return -1; + } + + r = cap_get_flag(cap_d, values[i], CAP_EFFECTIVE, &eff_state); + if (r != 0) { + _E("Failed to get cap eff - errno(%d)", errno); + cap_free(cap_d); + return -1; + } + + if ((inh_state != CAP_SET) || (eff_state != CAP_SET)) { + _E("The %s doesn't have %d cap", loader, values[i]); + cap_free(cap_d); + return -1; + } + } + cap_free(cap_d); + + return 0; +} + +static void __get_app_type_string(const launchpad::LoaderInfoPtr& info, + char buf[], int size) { + char* ptr = buf; + + for (auto& app_type : info->GetAppTypes()) { + if (size < app_type.size() + 1) + return; + + strncpy(ptr, app_type.c_str(), size); + ptr += app_type.size(); + size -= app_type.size(); + (*ptr++) = ' '; + size--; + } +} + +static void __add_slot_from_info(const launchpad::LoaderInfoPtr& info) { + candidate_process_context_t* cpc; + bundle_raw* extra = nullptr; + int len; + char buf[2048] = { + 0, + }; + + // TODO(changyu.choi): slot_info will be implemented to refer to loader_info + slot_info_t slot_info = { + .type = LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset, + .loader_name = info->GetName().c_str(), + .loader_path = info->GetExe().c_str(), + .threshold_max = info->GetCpuThresholdMax(), + .threshold_min = info->GetCpuThresholdMin(), + .app_exists = info->IsAppExists(), + .is_hydra = info->IsHydraEnabled(), + .app_check = info->IsNeededAppCheck(), + .on_boot_timeout = info->GetOnbootTimeout(), + .sched_priority = info->GetSchedPriority() + }; + + if (info->GetExe() == "null") { + slot_info.loader_id = PAD_LOADER_ID_DIRECT; + + cpc = __add_slot(&slot_info); + if (cpc == nullptr) + return; + + info->SetType(static_cast( + static_cast(launchpad::LoaderType::User) + user_slot_offset)); + user_slot_offset++; + return; + } else if (access(info->GetExe().c_str(), F_OK | X_OK) == 0) { + if (__verify_loader_caps(info->GetExe().c_str()) < 0) + return; + + bundle_encode(info->GetExtra().GetHandle(), &extra, &len); + + slot_info.loader_id = PAD_LOADER_ID_STATIC; + 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.ttl = info->GetTtl(); + slot_info.timeout_val = info->GetTimeoutVal(); + slot_info.on_boot = info->IsOnBoot(); + + cpc = __add_slot(&slot_info); + bundle_free_encoded_rawdata(&extra); + if (cpc == nullptr) + return; + + info->SetType(static_cast( + 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())); + } +} + +static int __add_default_slots(void) { + loader_info_manager = + std::make_unique(LOADER_INFO_PATH); + + loader_info_manager->Load(); + user_slot_offset = 0; + for (auto& info : loader_info_manager->GetLoaderInfoList()) { + __add_slot_from_info(info); + } + __add_idle_checker(0, candidate_slot_list); + + return 0; +} + +static void __add_app_defined_loaders(void) { + app_defined_loader_info_manager = + std::make_unique( + APP_DEFINED_LOADER_INFO_PATH); + + app_defined_loader_info_manager->Load(); +} + +static bool __is_low_memory(void) { + if (_memory_monitor_is_low_memory()) + return true; + + if (__memory_status_low >= MEMORY_STATUS_LOW) + return true; + + return false; +} + +static void __hw_acceleration_changed_cb(keynode_t* key, void* data) { + __sys_hwacc = vconf_keynode_get_int(key); + _D("sys hwacc: %d", __sys_hwacc); +} + +static void __update_lang(keynode_t* node, void* user_data) { + char* lang; + + lang = vconf_keynode_get_str(node); + if (!lang) { + _E("Failed to get language"); + return; + } + + setenv("LANG", lang, 1); +} + +static void __region_format_changed_cb(keynode_t* node, void* data) { + char* region; + + region = vconf_keynode_get_str(node); + if (!region) { + _E("Failed to get value"); + return; + } + + setenv("LC_CTYPE", region, 1); +} + +static void __memory_status_low_changed_cb(keynode_t* node, void* data) { + candidate_process_context_t* cpc; + GList* iter; + + __memory_status_low = vconf_keynode_get_int(node); + if (__memory_status_low >= MEMORY_STATUS_LOW) { + _W("Low memory"); + iter = candidate_slot_list; + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + __update_slot_state(cpc, launchpad::LoaderMethod::OutOfMemory, false); + iter = g_list_next(iter); + } + } +} + +static void __memory_status_normal_changed_cb(keynode_t* node, void* data) { + candidate_process_context_t* cpc; + GList* iter; + + __memory_status_normal = vconf_keynode_get_int(node); + if (__memory_status_normal == MEMORY_STATUS_NORMAL) { + _W("Normal"); + iter = candidate_slot_list; + while (iter) { + cpc = (candidate_process_context_t*)iter->data; + __update_slot_state(cpc, launchpad::LoaderMethod::AvailableMemory, true); + iter = g_list_next(iter); + } + } +} + +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); + + 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); +} + +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) + _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); + if (r != VCONF_OK) { + _E("Failed to register callback for hw acceleration. err = %d", r); + } + + lang = vconf_get_str(VCONFKEY_LANGSET); + if (lang) { + setenv("LANG", lang, 1); + free(lang); + } + + r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, nullptr); + if (r != VCONF_OK) + _E("Failed to register callback for langset. err = %d", r); + + region = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (region) { + setenv("LC_CTYPE", region, 1); + free(region); + } + + r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, + __region_format_changed_cb, nullptr); + 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); + 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); + 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); + 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); + if (r != 0) + _E("Failed to register callback for normal memory. err = %d", r); + + return 0; +} + +static bool __handle_logger(int fd, io_condition_e cond, void* data) { + app_pkt_t* pkt; + struct ucred cr; + int clifd = -1; + + if (cond & (IO_ERR | IO_HUP | IO_NVAL)) { + _E("fd(%d), io_condition(%d)", fd, cond); + g_idle_add(__logger_recovery_cb, __logger_channel); + __logger_channel = nullptr; + return false; + } + + pkt = _accept_recv_pkt_raw(fd, &clifd, &cr); + if (!pkt) { + _E("Failed to receive the packet"); + return true; + } + + if (getuid() != cr.uid) { + _E("Invalid caller"); + goto end; + } + + if (pkt->len <= 0) { + _E("Invalid message"); + goto end; + } + + _E("[%d] %s", cr.pid, (const char*)pkt->data); + _log_print("[ERROR]", "pid(%7d) | message(%s)", cr.pid, + (const char*)pkt->data); +end: + if (clifd != -1) + close(clifd); + + free(pkt); + + return true; +} + +static int __init_logger_fd(void) { + int fd; + + fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK); + if (fd < 0) { + _E("Failed to create logger socker"); + return -1; + } + + auto cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; + __logger_channel = _io_channel_create(fd, static_cast(cond), + __handle_logger, nullptr); + if (!__logger_channel) { + close(fd); + return -1; + } + + 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; + + if (low_memory) { + _W("Low memory"); + __update_slots_pss(); + + candidate_slot_list = g_list_sort(candidate_slot_list, __compare_slot); + __pause_all_running_slots(false); + } else { + __resume_all_slots(); + } + + return 0; +} + +static gboolean __logger_recovery_cb(gpointer data) { + auto channel = static_cast(data); + int ret; + + _io_channel_destroy(channel); + + ret = __init_logger_fd(); + if (ret < 0) { + _E("Failed to recover logger socket"); + return G_SOURCE_REMOVE; + } + + _E("[__RECOVERY__] Logger socket"); + + return G_SOURCE_REMOVE; +} + +static gboolean __launchpad_recovery_cb(gpointer data) { + auto channel = static_cast(data); + int ret; + + _io_channel_destroy(channel); + + ret = __init_launchpad_fd(0, nullptr); + if (ret < 0) { + _E("Failed to recover launchpad socket"); + abort(); + return G_SOURCE_REMOVE; + } + + _E("[__RECOVERY__] Launchpad socket"); + + return G_SOURCE_REMOVE; +} + +static int __before_loop(int argc, char** argv) { + __request_handlers[PAD_CMD_VISIBILITY] = __visibility_request_handler; + __request_handlers[PAD_CMD_ADD_LOADER] = __add_loader_request_handler; + __request_handlers[PAD_CMD_REMOVE_LOADER] = __remove_loader_request_handler; + __request_handlers[PAD_CMD_MAKE_DEFAULT_SLOTS] = + __make_default_slots_request_handler; + __request_handlers[PAD_CMD_PREPARE_APP_DEFINED_LOADER] = + __prepare_app_defined_loader_request_handler; + __request_handlers[PAD_CMD_DEMAND] = __demand_request_handler; + __request_handlers[PAD_CMD_PING] = __ping_request_handler; + __request_handlers[PAD_CMD_UPDATE_APP_TYPE] = + __update_app_type_request_handler; + __request_handlers[PAD_CMD_CONNECT] = __connect_request_handler; + __request_handlers[PAD_CMD_LAUNCH] = __launch_request_handler; + + _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__); + int ret = __sequencer_init(); + if (ret < 0) { + _E("Failed to initialize sequencer"); + return -1; + } + + ret = _signal_init(); + if (ret < 0) { + _E("Failed to initialize signal"); + return -1; + } + + _signal_set_sigchld_cb(__handle_sigchild, nullptr); + + ret = __init_launchpad_fd(argc, argv); + if (ret != 0) { + _E("__init_launchpad_fd() failed"); + return -1; + } + + ret = __init_logger_fd(); + if (ret != 0) { + _E("__init_logger_fd() failed"); + return -1; + } + + ret = __init_label_monitor_fd(); + if (ret != 0) + _W("Failed to initialize label monitor"); + + ret = _config_init(); + if (ret != 0) + _W("Failed to initialize config"); + + ret = _dbus_init(); + if (ret != 0) + _W("Failed to initialize dbus"); + + _inotify_init(); + + MAX_CPU_CHECK_COUNT = + _config_get_int_value(CONFIG_TYPE_CPU_CHECKER_MAX_COUNT); + __add_default_slots(); + + launchpad::LauncherInfoInflator inflator; + launcher_info_list = inflator.Inflate(LAUNCHER_INFO_PATH); + + __add_app_defined_loaders(); + + ret = _send_cmd_to_amd(LAUNCHPAD_LAUNCH_SIGNAL); + if (ret < 0) + _W("Failed to send cmd(%d) to amd", LAUNCHPAD_LAUNCH_SIGNAL); + + __pid_table = + g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr, free); + if (!__pid_table) { + _E("Failed to create pid table"); + return -1; + } + + ret = _worker_create("cleaner+", &__cleaner); + if (ret < 0) + return ret; + + __register_vconf_events(); + __init_app_defined_loader_monitor(); + _memory_monitor_init(); + _memory_monitor_set_event_cb(__memory_monitor_cb, nullptr); + _log_init(); + _print_hwc_log("%s(%d): END", __FUNCTION__, __LINE__); + + return 0; +} + +static void __after_loop(void) { + _log_fini(); + _memory_monitor_fini(); + __unregister_vconf_events(); + _worker_destroy(__cleaner); + if (__pid_table) + g_hash_table_destroy(__pid_table); + + if (_send_cmd_to_amd(LAUNCHPAD_DEAD_SIGNAL) < 0) + _W("Failed to send cmd(%d) to amd", LAUNCHPAD_DEAD_SIGNAL); + + _debug_fini(); + launcher_info_list.clear(); + _dbus_fini(); + _config_fini(); + _inotify_fini(); + app_defined_loader_info_manager->Dispose(); + + if (__label_monitor_channel) + _io_channel_destroy(__label_monitor_channel); + + if (label_monitor) + security_manager_app_labels_monitor_finish(label_monitor); + + if (__logger_channel) + _io_channel_destroy(__logger_channel); + + if (__launchpad_channel) + _io_channel_destroy(__launchpad_channel); + + _signal_fini(); + + __sequencer_fini(); +} + +int main(int argc, char** argv) { + GMainLoop* mainloop = nullptr; + + _print_hwc_log("%s(%d): START", __FUNCTION__, __LINE__); + prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); + + mainloop = g_main_loop_new(nullptr, FALSE); + if (!mainloop) { + _E("Failed to create glib main loop"); + return -1; + } + + _print_hwc_log("%s(%d): __before_loop()", __FUNCTION__, __LINE__); + if (__before_loop(argc, argv) != 0) { + _E("process-pool Initialization failed!"); + return -1; + } + +#ifdef TIZEN_FEATURE_PRIORITY_CHANGE + _set_priority(-12); +#endif + _print_hwc_log("%s(%d): g_main_loop_run()", __FUNCTION__, __LINE__); + g_main_loop_run(mainloop); + + __after_loop(); + + return -1; +} diff --git a/src/launchpad-process-pool/src/launchpad_config.c b/src/launchpad-process-pool/src/launchpad_config.cc similarity index 99% rename from src/launchpad-process-pool/src/launchpad_config.c rename to src/launchpad-process-pool/src/launchpad_config.cc index b1be6ea..33a448f 100644 --- a/src/launchpad-process-pool/src/launchpad_config.c +++ b/src/launchpad-process-pool/src/launchpad_config.cc @@ -14,7 +14,6 @@ * limitations under the License. */ -#define _GNU_SOURCE #include #include #include diff --git a/src/launchpad-process-pool/src/launchpad_dbus.c b/src/launchpad-process-pool/src/launchpad_dbus.c deleted file mode 100644 index 0b3f298..0000000 --- a/src/launchpad-process-pool/src/launchpad_dbus.c +++ /dev/null @@ -1,299 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include - -#include "launchpad_dbus.h" -#include "log_private.h" - -#define AUL_DBUS_PATH "/aul/dbus_handler" -#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" -#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" -#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" - -#define PENDING_ITEM_INTERVAL 1000 - -#define GET_CONNECTION_ERROR_THRESHOLD 10 -#define GET_CONNECTION_ERROR_MODULO 1000 -typedef enum { - APP_SIGNAL_DEAD, - APP_SIGNAL_LAUNCH, -} app_signal_e; - -typedef struct pending_item_s { - char *app_id; - int pid; - app_signal_e app_signal; -} pending_item_t; - -static GList *__pending_items; -static guint __timer; -static GDBusConnection *__conn; - -static void __set_pending_item_timer(void); - -static void __destroy_pending_item(gpointer data) -{ - pending_item_t *item = data; - - free(item->app_id); - free(item); -} - -static pending_item_t *__create_pending_item(const char *app_id, - int pid, app_signal_e app_signal) -{ - pending_item_t *item; - - item = calloc(1, sizeof(pending_item_t)); - if (!item) { - _E("Out of memory"); - return NULL; - } - - if (app_id) { - item->app_id = strdup(app_id); - if (!item->app_id) { - _E("Failed to duplicate app ID(%s)", app_id); - __destroy_pending_item(item); - return NULL; - } - } - - item->pid = pid; - item->app_signal = app_signal; - - return item; -} - -static GDBusConnection *__get_connection(void) -{ - GError *error = NULL; - static unsigned int error_count = 0; - - if (__conn) - return __conn; - - __conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (!__conn) { - error_count++; - if (error_count < GET_CONNECTION_ERROR_THRESHOLD || - error_count % GET_CONNECTION_ERROR_MODULO == 0) { - _E("g_bus_get_sync() is failed. error(%s)", - error ? error->message : "Unknown"); - } - - g_clear_error(&error); - return NULL; - } - - return __conn; -} - -static int __emit_signal(const char *path, - const char *interface, - const char *signal, - GVariant *param) -{ - GDBusConnection *conn; - GError *error = NULL; - gboolean ret; - - conn = __get_connection(); - if (!conn) - return -1; - - ret = g_dbus_connection_emit_signal(conn, - NULL, - path, - interface, - signal, - param, - &error); - if (ret != TRUE) { - _E("g_dbus_connection_emit_signal() is failed. error(%s)", - error ? error->message : "Unknown"); - g_clear_error(&error); - return -1; - } - - ret = g_dbus_connection_flush_sync(conn, NULL, &error); - if (ret != TRUE) { - _E("g_dbus_connection_flush_sync() is failed. error(%s)", - error ? error->message : "Unknown"); - g_clear_error(&error); - return -1; - } - - return 0; -} - -static int __emit_app_launch_signal(int pid, const char *app_id) -{ - int ret; - - ret = __emit_signal(AUL_DBUS_PATH, - AUL_DBUS_SIGNAL_INTERFACE, - AUL_DBUS_APPLAUNCH_SIGNAL, - g_variant_new("(us)", pid, app_id)); - if (ret < 0) - return ret; - - _D("App launch. pid(%d), app_id(%s)", pid, app_id); - - return 0; -} - -static int __emit_app_dead_signal(int pid) -{ - int ret; - - ret = __emit_signal(AUL_DBUS_PATH, - AUL_DBUS_SIGNAL_INTERFACE, - AUL_DBUS_APPDEAD_SIGNAL, - g_variant_new("(u)", pid)); - if (ret < 0) - return ret; - - _D("App dead. pid(%d)", pid); - - return 0; -} - -static gboolean __flush_pending_item(gpointer data) -{ - pending_item_t *item; - GList *iter; - int ret; - - if (!__pending_items) { - __timer = 0; - return G_SOURCE_REMOVE; - } - - iter = __pending_items; - while (iter) { - item = (pending_item_t *)iter->data; - if (item->app_signal == APP_SIGNAL_DEAD) - ret = __emit_app_dead_signal(item->pid); - else - ret = __emit_app_launch_signal(item->pid, item->app_id); - - if (ret < 0) - return G_SOURCE_CONTINUE; - - iter = g_list_next(iter); - __pending_items = g_list_remove(__pending_items, item); - __destroy_pending_item(item); - } - - __timer = 0; - return G_SOURCE_REMOVE; -} - -static void __set_pending_item_timer(void) -{ - if (__timer) - return; - - __timer = g_timeout_add(PENDING_ITEM_INTERVAL, - __flush_pending_item, NULL); -} - -static void __unset_pending_item_timer(void) -{ - if (!__timer) - return; - - g_source_remove(__timer); - __timer = 0; -} - -int _dbus_send_app_launch_signal(int pid, const char *app_id) -{ - pending_item_t *item; - int ret; - - if (pid <= 1 || !app_id) { - _E("Invalid parameter"); - return -EINVAL; - } - - ret = __emit_app_launch_signal(pid, app_id); - if (ret < 0) { - item = __create_pending_item(app_id, pid, APP_SIGNAL_LAUNCH); - if (!item) - return -ENOMEM; - - _W("Pend app launch signal. pid(%d), app_id(%s)", pid, app_id); - __pending_items = g_list_append(__pending_items, item); - __set_pending_item_timer(); - } - - return 0; -} - -int _dbus_send_app_dead_signal(int pid) -{ - pending_item_t *item; - int ret; - - if (pid <= 1) { - _E("Invalid parameter"); - return -EINVAL; - } - - ret = __emit_app_dead_signal(pid); - if (ret < 0) { - item = __create_pending_item(NULL, pid, APP_SIGNAL_DEAD); - if (!item) - return -ENOMEM; - - _W("Pend app dead signal. pid(%d)", pid); - __pending_items = g_list_append(__pending_items, item); - __set_pending_item_timer(); - } - - return 0; -} - -int _dbus_init(void) -{ - GDBusConnection *conn; - - _D("DBUS_INIT"); - conn = __get_connection(); - if (!conn) - return -1; - - return 0; -} - -void _dbus_fini(void) -{ - _D("DBUS_FINI"); - if (__pending_items) - g_list_free_full(__pending_items, __destroy_pending_item); - - __unset_pending_item_timer(); - - if (__conn) - g_object_unref(__conn); -} diff --git a/src/launchpad-process-pool/src/launchpad_dbus.cc b/src/launchpad-process-pool/src/launchpad_dbus.cc new file mode 100644 index 0000000..7beff3d --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_dbus.cc @@ -0,0 +1,277 @@ +/* + * 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 +#include +#include +#include + +#include "launchpad_dbus.h" +#include "log_private.h" + +#define AUL_DBUS_PATH "/aul/dbus_handler" +#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" +#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" +#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" + +#define PENDING_ITEM_INTERVAL 1000 + +#define GET_CONNECTION_ERROR_THRESHOLD 10 +#define GET_CONNECTION_ERROR_MODULO 1000 +typedef enum { + APP_SIGNAL_DEAD, + APP_SIGNAL_LAUNCH, +} app_signal_e; + +typedef struct pending_item_s { + char* app_id; + int pid; + app_signal_e app_signal; +} pending_item_t; + +static GList* __pending_items; +static guint __timer; +static GDBusConnection* __conn; + +static void __set_pending_item_timer(void); + +static void __destroy_pending_item(gpointer data) { + auto* item = static_cast(data); + + free(item->app_id); + free(item); +} + +static pending_item_t* __create_pending_item(const char* app_id, + int pid, + app_signal_e app_signal) { + pending_item_t* item; + + item = static_cast(calloc(1, sizeof(pending_item_t))); + if (!item) { + _E("Out of memory"); + return nullptr; + } + + if (app_id) { + item->app_id = strdup(app_id); + if (!item->app_id) { + _E("Failed to duplicate app ID(%s)", app_id); + __destroy_pending_item(item); + return nullptr; + } + } + + item->pid = pid; + item->app_signal = app_signal; + + return item; +} + +static GDBusConnection* __get_connection(void) { + GError* error = nullptr; + static unsigned int error_count = 0; + + if (__conn) + return __conn; + + __conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error); + if (!__conn) { + error_count++; + if (error_count < GET_CONNECTION_ERROR_THRESHOLD || + error_count % GET_CONNECTION_ERROR_MODULO == 0) { + _E("g_bus_get_sync() is failed. error(%s)", + error ? error->message : "Unknown"); + } + + g_clear_error(&error); + return nullptr; + } + + return __conn; +} + +static int __emit_signal(const char* path, + const char* interface, + const char* signal, + GVariant* param) { + GDBusConnection* conn; + GError* error = nullptr; + gboolean ret; + + conn = __get_connection(); + if (!conn) + return -1; + + ret = g_dbus_connection_emit_signal(conn, nullptr, path, interface, signal, + param, &error); + if (ret != TRUE) { + _E("g_dbus_connection_emit_signal() is failed. error(%s)", + error ? error->message : "Unknown"); + g_clear_error(&error); + return -1; + } + + ret = g_dbus_connection_flush_sync(conn, nullptr, &error); + if (ret != TRUE) { + _E("g_dbus_connection_flush_sync() is failed. error(%s)", + error ? error->message : "Unknown"); + g_clear_error(&error); + return -1; + } + + return 0; +} + +static int __emit_app_launch_signal(int pid, const char* app_id) { + int ret; + + ret = __emit_signal(AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPLAUNCH_SIGNAL, + g_variant_new("(us)", pid, app_id)); + if (ret < 0) + return ret; + + _D("App launch. pid(%d), app_id(%s)", pid, app_id); + + return 0; +} + +static int __emit_app_dead_signal(int pid) { + int ret; + + ret = __emit_signal(AUL_DBUS_PATH, AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPDEAD_SIGNAL, g_variant_new("(u)", pid)); + if (ret < 0) + return ret; + + _D("App dead. pid(%d)", pid); + + return 0; +} + +static gboolean __flush_pending_item(gpointer data) { + pending_item_t* item; + GList* iter; + int ret; + + if (!__pending_items) { + __timer = 0; + return G_SOURCE_REMOVE; + } + + iter = __pending_items; + while (iter) { + item = (pending_item_t*)iter->data; + if (item->app_signal == APP_SIGNAL_DEAD) + ret = __emit_app_dead_signal(item->pid); + else + ret = __emit_app_launch_signal(item->pid, item->app_id); + + if (ret < 0) + return G_SOURCE_CONTINUE; + + iter = g_list_next(iter); + __pending_items = g_list_remove(__pending_items, item); + __destroy_pending_item(item); + } + + __timer = 0; + return G_SOURCE_REMOVE; +} + +static void __set_pending_item_timer(void) { + if (__timer) + return; + + __timer = g_timeout_add(PENDING_ITEM_INTERVAL, __flush_pending_item, nullptr); +} + +static void __unset_pending_item_timer(void) { + if (!__timer) + return; + + g_source_remove(__timer); + __timer = 0; +} + +int _dbus_send_app_launch_signal(int pid, const char* app_id) { + pending_item_t* item; + int ret; + + if (pid <= 1 || !app_id) { + _E("Invalid parameter"); + return -EINVAL; + } + + ret = __emit_app_launch_signal(pid, app_id); + if (ret < 0) { + item = __create_pending_item(app_id, pid, APP_SIGNAL_LAUNCH); + if (!item) + return -ENOMEM; + + _W("Pend app launch signal. pid(%d), app_id(%s)", pid, app_id); + __pending_items = g_list_append(__pending_items, item); + __set_pending_item_timer(); + } + + return 0; +} + +int _dbus_send_app_dead_signal(int pid) { + pending_item_t* item; + int ret; + + if (pid <= 1) { + _E("Invalid parameter"); + return -EINVAL; + } + + ret = __emit_app_dead_signal(pid); + if (ret < 0) { + item = __create_pending_item(nullptr, pid, APP_SIGNAL_DEAD); + if (!item) + return -ENOMEM; + + _W("Pend app dead signal. pid(%d)", pid); + __pending_items = g_list_append(__pending_items, item); + __set_pending_item_timer(); + } + + return 0; +} + +int _dbus_init(void) { + GDBusConnection* conn; + + _D("DBUS_INIT"); + conn = __get_connection(); + if (!conn) + return -1; + + return 0; +} + +void _dbus_fini(void) { + _D("DBUS_FINI"); + if (__pending_items) + g_list_free_full(__pending_items, __destroy_pending_item); + + __unset_pending_item_timer(); + + if (__conn) + g_object_unref(__conn); +} diff --git a/src/launchpad-process-pool/src/launchpad_debug.c b/src/launchpad-process-pool/src/launchpad_debug.c deleted file mode 100644 index da59159..0000000 --- a/src/launchpad-process-pool/src/launchpad_debug.c +++ /dev/null @@ -1,451 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debugger_info.h" -#include "key.h" -#include "launchpad_common.h" -#include "launchpad_debug.h" -#include "launchpad_types.h" - -#define DEBUGGER_INFO_PATH "/usr/share/aul" - -static int __debug_initialized; -static GList *__debugger_info_list; -static debugger_info_h __debugger_info; -static GList *__debug_argv_list; -static GList *__extra_argv_list; - -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 == NULL) - 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; - const char *extra_argv; - GList *iter; - int i; - - if (argc == NULL || argv == NULL) { - _E("[DEBUG] Invalid parameter"); - return -1; - } - - if (__debugger_info == NULL) - return 0; - - new_argc = g_list_length(__extra_argv_list); - if (new_argc == 0) - return 0; - - new_argv = (char **)calloc(new_argc, sizeof(char *)); - if (new_argv == NULL) { - _E("out of memory"); - return -1; - } - - i = LOADER_ARG_PATH; - iter = g_list_first(__extra_argv_list); - while (iter) { - extra_argv = (const char *)iter->data; - if (extra_argv) - new_argv[i++] = strdup(extra_argv); - - iter = g_list_next(iter); - } - - *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 *debug_argv; - const char *attach_str; - GList *iter; - GList *list; - int i; - - if (argc == NULL || argv == NULL || attach == NULL) { - _E("[DEBUG] Invalid parameter"); - return -1; - } - - if (__debugger_info == NULL) - return 0; - - exe = _debugger_info_get_exe(__debugger_info); - if (exe == NULL) - return 0; - - attach_str = _debugger_info_get_attach(__debugger_info); - if (attach_str && strcasecmp(attach_str, "true") == 0) { - *attach = true; - new_argc++; - } - - list = _debugger_info_get_default_opt_list(__debugger_info); - new_argc += g_list_length(__debug_argv_list) + g_list_length(list) + 1; - new_argv = (char **)calloc(new_argc, sizeof(char *)); - if (new_argv == NULL) { - _E("out of memory"); - return -1; - } - - i = LOADER_ARG_PATH; - new_argv[i++] = strdup(exe); - - iter = g_list_first(list); - while (iter) { - debug_argv = (const char *)iter->data; - if (debug_argv) - new_argv[i++] = strdup(debug_argv); - - iter = g_list_next(iter); - } - - iter = g_list_first(__debug_argv_list); - while (iter) { - debug_argv = (const char *)iter->data; - if (debug_argv) - new_argv[i++] = strdup(debug_argv); - - iter = g_list_next(iter); - } - - *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 == NULL) - 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 == NULL) - pid_str = bundle_get_val(kb, AUL_K_CALLER_PID); - - if (pid_str == NULL) - 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 == NULL) { - _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(gpointer data, gpointer user_data) -{ - const char *key = (const char *)data; - bundle *kb = (bundle *)user_data; - const char *str; - const char **str_arr = NULL; - int len = 0; - int i; - - if (key == NULL || kb == NULL) - return; - - _D("[DEBUG] key: %s", key); - if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) { - str_arr = bundle_get_str_array(kb, key, &len); - } else { - str = bundle_get_val(kb, key); - if (str) { - str_arr = &str; - len = 1; - } - } - - for (i = 0; i < len; i++) { - if (str_arr[i] == NULL) - break; - - __extra_argv_list = g_list_append(__extra_argv_list, - strdup(str_arr[i])); - } - - if (str_arr) - bundle_del(kb, key); -} - -static void __add_debug_argv(gpointer data, gpointer user_data) -{ - const char *key = (const char *)data; - bundle *kb = (bundle *)user_data; - const char *str; - const char **str_arr = NULL; - int len = 0; - int i; - - if (key == NULL || kb == NULL) - return; - - _D("[DEBUG] key: %s", key); - if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) { - str_arr = bundle_get_str_array(kb, key, &len); - } else { - str = bundle_get_val(kb, key); - if (str) { - str_arr = &str; - len = 1; - } - } - - for (i = 0; i < len; i++) { - if (str_arr[i] == NULL) - break; - - __debug_argv_list = g_list_append(__debug_argv_list, - strdup(str_arr[i])); - if (!strcmp(key, "__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); -} - -static void __set_debug_env(gpointer data, gpointer user_data) -{ - const char *key = (const char *)data; - bundle *kb = (bundle *)user_data; - const char *str; - const char **str_arr = NULL; - int len = 0; - int i; - char buf[LINE_MAX] = {0,}; - - if (key == NULL || kb == NULL) - return; - - _D("[DEBUG] key: %s", key); - if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) { - str_arr = bundle_get_str_array(kb, key, &len); - } else { - str = bundle_get_val(kb, key); - if (str) { - str_arr = &str; - len = 1; - } - } - - if (str_arr == NULL) - return; - - strncat(buf, str_arr[0], sizeof(buf) - strlen(buf) - 1); - for (i = 1; i < len; i++) { - if (str_arr[i] == NULL) - break; - - strncat(buf, ",", sizeof(buf) - strlen(buf) - 1); - strncat(buf, str_arr[i], sizeof(buf) - strlen(buf) - 1); - } - - bundle_del(kb, key); - _D("[DEBUG] name: %s, value: %s", key, buf); - setenv(key, buf, 1); -} - -static void __remove_file(gpointer data, gpointer user_data) -{ - const char *file = (const char *)data; - - if (file == NULL) - return; - - _D("[DEBUG] file: %s", file); - if (access(file, F_OK) == 0) { - if (remove(file) != 0) - _W("[DEBUG] Failed to remove %s", file); - } -} - -void _debug_prepare_debugger(bundle *kb) -{ - const char *debugger; - GList *list; - int ret; - - if (kb == NULL) - return; - - debugger = bundle_get_val(kb, AUL_K_SDK); - if (debugger == NULL) - 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); - __debugger_info = _debugger_info_find(__debugger_info_list, debugger); - if (__debugger_info == NULL) - return; - - list = _debugger_info_get_unlink_list(__debugger_info); - g_list_foreach(list, __remove_file, NULL); - - list = _debugger_info_get_extra_env_list(__debugger_info); - g_list_foreach(list, __set_debug_env, kb); - - list = _debugger_info_get_extra_key_list(__debugger_info); - g_list_foreach(list, __add_debug_argv, kb); - - list = _debugger_info_get_last_extra_key_list(__debugger_info); - g_list_foreach(list, __add_extra_argv, kb); -} - -int _debug_init(void) -{ - if (__debug_initialized) - return 0; - - __debugger_info_list = _debugger_info_load(DEBUGGER_INFO_PATH); - if (__debugger_info_list == NULL) - return -1; - - __debug_initialized = 1; - - return 0; -} - -void _debug_fini(void) -{ - if (!__debug_initialized) - return; - - _debugger_info_unload(__debugger_info_list); -} diff --git a/src/launchpad-process-pool/src/launchpad_debug.cc b/src/launchpad-process-pool/src/launchpad_debug.cc new file mode 100644 index 0000000..12f8bdc --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_debug.cc @@ -0,0 +1,412 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "debugger_info.hh" +#include "key.h" +#include "launchpad_common.h" +#include "launchpad_debug.h" +#include "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/src/launchpad_inotify.c b/src/launchpad-process-pool/src/launchpad_inotify.c deleted file mode 100644 index 9130fa2..0000000 --- a/src/launchpad-process-pool/src/launchpad_inotify.c +++ /dev/null @@ -1,191 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include - -#include "launchpad_inotify.h" -#include "log_private.h" - -struct inotify_watch_info_s { - int fd; - int wd; - GIOChannel *io; - guint tag; - uint32_t mask; - inotify_watch_cb cb; - void *data; -}; - -static GList *__watch_list; - -static gboolean __inotify_cb(GIOChannel *source, GIOCondition condition, - gpointer data) -{ -#define ALIGN_INOTIFY_EVENT \ - __attribute__ ((aligned(__alignof__(struct inotify_event)))) -#define SIZE_INOTIFY_EVENT (sizeof(struct inotify_event)) - int fd = g_io_channel_unix_get_fd(source); - char buf[4096] ALIGN_INOTIFY_EVENT; - const struct inotify_event *event; - struct inotify_watch_info_s *info = data; - ssize_t len; - char *ptr; - char *nptr; - - while ((len = read(fd, buf, sizeof(buf))) > 0) { - for (ptr = buf; ptr < buf + len; - ptr += sizeof(struct inotify_event) + event->len) { - if ((ptr + SIZE_INOTIFY_EVENT) > (buf + len)) - break; - - event = (const struct inotify_event *)ptr; - nptr = ptr + sizeof(struct inotify_event) + event->len; - if (nptr > buf + len) - break; - - if (event->mask & info->mask) { - if (!info->cb(event->name, event->mask, - info->data)) { - _inotify_rm_watch(info); - return G_SOURCE_CONTINUE; - } - } - } - } - - return G_SOURCE_CONTINUE; -} - -static void __destroy_inotify_watch_info(gpointer data) -{ - struct inotify_watch_info_s *info = (struct inotify_watch_info_s *)data; - - if (info == NULL) - return; - - if (info->tag > 0) - g_source_remove(info->tag); - - if (info->io) - g_io_channel_unref(info->io); - - if (info->wd > 0) - inotify_rm_watch(info->fd, info->wd); - - if (info->fd > 0) - close(info->fd); - - free(info); -} - -static struct inotify_watch_info_s *__create_inotify_watch_info( - const char *path, uint32_t mask, inotify_watch_cb cb, - void *data) -{ - GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP; - struct inotify_watch_info_s *info; - - info = calloc(1, sizeof(struct inotify_watch_info_s)); - if (info == NULL) { - _E("Out of memory"); - return NULL; - } - - info->fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); - if (info->fd < 0) { - _E("inotify_init1() is failed. errno(%d)", errno); - __destroy_inotify_watch_info(info); - return NULL; - } - - info->wd = inotify_add_watch(info->fd, path, mask); - if (info->wd < 0) { - _E("inotify_add_watch() is failed. path(%s), errno(%d)", - path, errno); - __destroy_inotify_watch_info(info); - return NULL; - } - - info->io = g_io_channel_unix_new(info->fd); - if (!info->io) { - _E("g_io_channel_unix_new() is failed"); - __destroy_inotify_watch_info(info); - return NULL; - } - - info->tag = g_io_add_watch(info->io, cond, - __inotify_cb, info); - if (!info->tag) { - _E("g_io_add_watch() is failed"); - __destroy_inotify_watch_info(info); - return NULL; - } - - info->mask = mask; - info->cb = cb; - info->data = data; - - return info; -} - -int _inotify_add_watch(const char *path, uint32_t mask, - inotify_watch_cb callback, void *data) -{ - struct inotify_watch_info_s *info; - - if (path == NULL || callback == NULL) { - _E("Invalid parameter"); - return -1; - } - - info = __create_inotify_watch_info(path, mask, callback, data); - if (info == NULL) - return -1; - - __watch_list = g_list_append(__watch_list, info); - - return 0; -} - -void _inotify_rm_watch(inotify_watch_info_h handle) -{ - if (handle == NULL) - return; - - __watch_list = g_list_remove(__watch_list, handle); - __destroy_inotify_watch_info(handle); -} - -int _inotify_init(void) -{ - _D("inotify init"); - - return 0; -} - -void _inotify_fini(void) -{ - _D("inotify fini"); - - if (__watch_list) - g_list_free_full(__watch_list, __destroy_inotify_watch_info); -} diff --git a/src/launchpad-process-pool/src/launchpad_inotify.cc b/src/launchpad-process-pool/src/launchpad_inotify.cc new file mode 100644 index 0000000..2afc91a --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_inotify.cc @@ -0,0 +1,187 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include "launchpad_inotify.h" +#include "log_private.h" + +struct inotify_watch_info_s { + int fd; + int wd; + GIOChannel* io; + guint tag; + uint32_t mask; + inotify_watch_cb cb; + void* data; +}; + +static GList* __watch_list; + +static gboolean __inotify_cb(GIOChannel* source, + GIOCondition condition, + gpointer data) { +#define ALIGN_INOTIFY_EVENT \ + __attribute__((aligned(__alignof__(struct inotify_event)))) +#define SIZE_INOTIFY_EVENT (sizeof(struct inotify_event)) + int fd = g_io_channel_unix_get_fd(source); + char buf[4096] ALIGN_INOTIFY_EVENT; + const struct inotify_event* event; + auto* info = static_cast(data); + ssize_t len; + char* ptr; + char* nptr; + + while ((len = read(fd, buf, sizeof(buf))) > 0) { + for (ptr = buf; ptr < buf + len; + ptr += sizeof(struct inotify_event) + event->len) { + if ((ptr + SIZE_INOTIFY_EVENT) > (buf + len)) + break; + + event = (const struct inotify_event*)ptr; + nptr = ptr + sizeof(struct inotify_event) + event->len; + if (nptr > buf + len) + break; + + if (event->mask & info->mask) { + if (!info->cb(event->name, event->mask, info->data)) { + _inotify_rm_watch(info); + return G_SOURCE_CONTINUE; + } + } + } + } + + return G_SOURCE_CONTINUE; +} + +static void __destroy_inotify_watch_info(gpointer data) { + struct inotify_watch_info_s* info = (struct inotify_watch_info_s*)data; + + if (info == nullptr) + return; + + if (info->tag > 0) + g_source_remove(info->tag); + + if (info->io) + g_io_channel_unref(info->io); + + if (info->wd > 0) + inotify_rm_watch(info->fd, info->wd); + + if (info->fd > 0) + close(info->fd); + + free(info); +} + +static struct inotify_watch_info_s* __create_inotify_watch_info( + const char* path, + uint32_t mask, + inotify_watch_cb cb, + void* data) { + auto cond = G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP; + struct inotify_watch_info_s* info; + + info = static_cast( + calloc(1, sizeof(inotify_watch_info_s))); + if (info == nullptr) { + _E("Out of memory"); + return nullptr; + } + + info->fd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); + if (info->fd < 0) { + _E("inotify_init1() is failed. errno(%d)", errno); + __destroy_inotify_watch_info(info); + return nullptr; + } + + info->wd = inotify_add_watch(info->fd, path, mask); + if (info->wd < 0) { + _E("inotify_add_watch() is failed. path(%s), errno(%d)", path, errno); + __destroy_inotify_watch_info(info); + return nullptr; + } + + info->io = g_io_channel_unix_new(info->fd); + if (!info->io) { + _E("g_io_channel_unix_new() is failed"); + __destroy_inotify_watch_info(info); + return nullptr; + } + + info->tag = g_io_add_watch(info->io, static_cast(cond), + __inotify_cb, info); + if (!info->tag) { + _E("g_io_add_watch() is failed"); + __destroy_inotify_watch_info(info); + return nullptr; + } + + info->mask = mask; + info->cb = cb; + info->data = data; + + return info; +} + +int _inotify_add_watch(const char* path, + uint32_t mask, + inotify_watch_cb callback, + void* data) { + struct inotify_watch_info_s* info; + + if (path == nullptr || callback == nullptr) { + _E("Invalid parameter"); + return -1; + } + + info = __create_inotify_watch_info(path, mask, callback, data); + if (info == nullptr) + return -1; + + __watch_list = g_list_append(__watch_list, info); + + return 0; +} + +void _inotify_rm_watch(inotify_watch_info_h handle) { + if (handle == nullptr) + return; + + __watch_list = g_list_remove(__watch_list, handle); + __destroy_inotify_watch_info(handle); +} + +int _inotify_init(void) { + _D("inotify init"); + + return 0; +} + +void _inotify_fini(void) { + _D("inotify fini"); + + if (__watch_list) + g_list_free_full(__watch_list, __destroy_inotify_watch_info); +} diff --git a/src/launchpad-process-pool/src/launchpad_io_channel.c b/src/launchpad-process-pool/src/launchpad_io_channel.c deleted file mode 100644 index 31529a3..0000000 --- a/src/launchpad-process-pool/src/launchpad_io_channel.c +++ /dev/null @@ -1,174 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include - -#include "launchpad_io_channel.h" -#include "log_private.h" - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) - -struct io_channel_s { - GIOChannel *io; - guint tag; - bool do_close; - int fd; - io_channel_event_cb callback; - void *user_data; -}; - -struct io_condition_s { - io_condition_e io_cond; - GIOCondition g_io_cond; -}; - -static struct io_condition_s __cond_map[] = { - { - .io_cond = IO_IN, - .g_io_cond = G_IO_IN - }, - { - .io_cond = IO_OUT, - .g_io_cond = G_IO_OUT - }, - { - .io_cond = IO_PRI, - .g_io_cond = G_IO_PRI - }, - { - .io_cond = IO_ERR, - .g_io_cond = G_IO_ERR - }, - { - .io_cond = IO_HUP, - .g_io_cond = G_IO_HUP - }, - { - .io_cond = IO_NVAL, - .g_io_cond = G_IO_NVAL, - } -}; - -static io_condition_e __convert_g_io_condition(GIOCondition cond) -{ - io_condition_e condition = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(__cond_map); i++) { - if (__cond_map[i].g_io_cond & cond) - condition |= __cond_map[i].io_cond; - } - - return condition; -} - -static GIOCondition __convert_io_condition(io_condition_e cond) -{ - GIOCondition condition = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(__cond_map); i++) { - if (__cond_map[i].io_cond & cond) - condition |= __cond_map[i].g_io_cond; - } - - return condition; -} - -static gboolean __io_event_cb(GIOChannel *source, GIOCondition condition, - gpointer data) -{ - io_channel_h channel = (io_channel_h)data; - io_condition_e cond = __convert_g_io_condition(condition); - int fd = g_io_channel_unix_get_fd(source); - - if (!channel->callback(fd, cond, channel->user_data)) - return G_SOURCE_REMOVE; - - return G_SOURCE_CONTINUE; -} - -io_channel_h _io_channel_create(int fd, io_condition_e cond, - io_channel_event_cb callback, void *user_data) -{ - struct io_channel_s *channel; - - if (fd < 3 || !callback) { - _E("Invalid parameter"); - return NULL; - } - - channel = calloc(1, sizeof(struct io_channel_s)); - if (!channel) { - _E("Out of memory"); - return NULL; - } - - channel->io = g_io_channel_unix_new(fd); - if (!channel->io) { - _E("Failed to create GIOChannel"); - _io_channel_destroy(channel); - return NULL; - } - - channel->tag = g_io_add_watch(channel->io, __convert_io_condition(cond), - __io_event_cb, channel); - if (!channel->tag) { - _E("Failed to add GIO watch"); - _io_channel_destroy(channel); - return NULL; - } - - channel->do_close = true; - channel->fd = fd; - channel->callback = callback; - channel->user_data = user_data; - - return channel; -} - -void _io_channel_destroy(io_channel_h channel) -{ - if (!channel) - return; - - if (channel->tag) - g_source_remove(channel->tag); - - if (channel->io) - g_io_channel_unref(channel->io); - - if (channel->do_close && channel->fd > 0) - close(channel->fd); - - free(channel); -} - -int _io_channel_set_close_on_destroy(io_channel_h channel, bool do_close) -{ - if (!channel) { - _E("Invalid parameter"); - return -EINVAL; - } - - channel->do_close = do_close; - - return 0; -} diff --git a/src/launchpad-process-pool/src/launchpad_io_channel.cc b/src/launchpad-process-pool/src/launchpad_io_channel.cc new file mode 100644 index 0000000..5987793 --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_io_channel.cc @@ -0,0 +1,154 @@ +/* + * 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 +#include +#include +#include + +#include "launchpad_io_channel.h" +#include "log_private.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +struct io_channel_s { + GIOChannel* io; + guint tag; + bool do_close; + int fd; + io_channel_event_cb callback; + void* user_data; +}; + +struct io_condition_s { + io_condition_e io_cond; + GIOCondition g_io_cond; +}; + +static struct io_condition_s __cond_map[] = { + {.io_cond = IO_IN, .g_io_cond = G_IO_IN}, + {.io_cond = IO_OUT, .g_io_cond = G_IO_OUT}, + {.io_cond = IO_PRI, .g_io_cond = G_IO_PRI}, + {.io_cond = IO_ERR, .g_io_cond = G_IO_ERR}, + {.io_cond = IO_HUP, .g_io_cond = G_IO_HUP}, + { + .io_cond = IO_NVAL, + .g_io_cond = G_IO_NVAL, + }}; + +static io_condition_e __convert_g_io_condition(GIOCondition cond) { + int condition = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(__cond_map); i++) { + if (__cond_map[i].g_io_cond & cond) + condition |= __cond_map[i].io_cond; + } + + return static_cast(condition); +} + +static GIOCondition __convert_io_condition(io_condition_e cond) { + int condition = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(__cond_map); i++) { + if (__cond_map[i].io_cond & cond) + condition |= __cond_map[i].g_io_cond; + } + + return static_cast(condition); +} + +static gboolean __io_event_cb(GIOChannel* source, + GIOCondition condition, + gpointer data) { + io_channel_h channel = (io_channel_h)data; + io_condition_e cond = __convert_g_io_condition(condition); + int fd = g_io_channel_unix_get_fd(source); + + if (!channel->callback(fd, cond, channel->user_data)) + return G_SOURCE_REMOVE; + + return G_SOURCE_CONTINUE; +} + +io_channel_h _io_channel_create(int fd, + io_condition_e cond, + io_channel_event_cb callback, + void* user_data) { + struct io_channel_s* channel; + + if (fd < 3 || !callback) { + _E("Invalid parameter"); + return nullptr; + } + + channel = static_cast(calloc(1, sizeof(io_channel_s))); + if (!channel) { + _E("Out of memory"); + return nullptr; + } + + channel->io = g_io_channel_unix_new(fd); + if (!channel->io) { + _E("Failed to create GIOChannel"); + _io_channel_destroy(channel); + return nullptr; + } + + channel->tag = g_io_add_watch(channel->io, __convert_io_condition(cond), + __io_event_cb, channel); + if (!channel->tag) { + _E("Failed to add GIO watch"); + _io_channel_destroy(channel); + return nullptr; + } + + channel->do_close = true; + channel->fd = fd; + channel->callback = callback; + channel->user_data = user_data; + + return channel; +} + +void _io_channel_destroy(io_channel_h channel) { + if (!channel) + return; + + if (channel->tag) + g_source_remove(channel->tag); + + if (channel->io) + g_io_channel_unref(channel->io); + + if (channel->do_close && channel->fd > 0) + close(channel->fd); + + free(channel); +} + +int _io_channel_set_close_on_destroy(io_channel_h channel, bool do_close) { + if (!channel) { + _E("Invalid parameter"); + return -EINVAL; + } + + channel->do_close = do_close; + + return 0; +} diff --git a/src/launchpad-process-pool/src/launchpad_log.c b/src/launchpad-process-pool/src/launchpad_log.cc similarity index 52% rename from src/launchpad-process-pool/src/launchpad_log.c rename to src/launchpad-process-pool/src/launchpad_log.cc index fc5d698..59128ab 100644 --- a/src/launchpad-process-pool/src/launchpad_log.c +++ b/src/launchpad-process-pool/src/launchpad_log.cc @@ -14,10 +14,9 @@ * limitations under the License. */ -#define _GNU_SOURCE +#include #include #include -#include #include "launchpad_config.h" #include "launchpad_log.h" @@ -29,47 +28,44 @@ static logger_h __logger; -int _log_print(const char *tag, const char *format, ...) -{ - char formatted_buf[LAUNCHPAD_LOG_MAX_STRING_SIZE]; - va_list ap; - int ret; +int _log_print(const char* tag, const char* format, ...) { + char formatted_buf[LAUNCHPAD_LOG_MAX_STRING_SIZE]; + va_list ap; + int ret; - if (!__logger) - return 0; + if (!__logger) + return 0; - va_start(ap, format); - ret = vsnprintf(formatted_buf, sizeof(formatted_buf), format, ap); - va_end(ap); - if (ret < 0 || ret >= sizeof(formatted_buf)) { - _E("vsnprintf() is failed. result(%d)", ret); - return -1; - } + va_start(ap, format); + ret = vsnprintf(formatted_buf, sizeof(formatted_buf), format, ap); + va_end(ap); + if (ret < 0 || ret >= sizeof(formatted_buf)) { + _E("vsnprintf() is failed. result(%d)", ret); + return -1; + } - return _logger_print(__logger, tag, formatted_buf); + return _logger_print(__logger, tag, formatted_buf); } -int _log_init(void) -{ - char path[PATH_MAX]; - int ret; +int _log_init(void) { + char path[PATH_MAX]; + int ret; - _W("LOG_INIT"); - snprintf(path, sizeof(path), "%s/launchpad/launchpad.log", - _config_get_string_value(CONFIG_TYPE_LOGGER_PATH)); - ret = _logger_create(path, &__logger); - if (ret != 0) { - _E("Failed to create log file. error(%d)", ret); - return ret; - } + _W("LOG_INIT"); + snprintf(path, sizeof(path), "%s/launchpad/launchpad.log", + _config_get_string_value(CONFIG_TYPE_LOGGER_PATH)); + ret = _logger_create(path, &__logger); + if (ret != 0) { + _E("Failed to create log file. error(%d)", ret); + return ret; + } - return 0; + return 0; } -void _log_fini(void) -{ - _W("LOG_FINI"); +void _log_fini(void) { + _W("LOG_FINI"); - if (__logger) - _logger_destroy(__logger); + if (__logger) + _logger_destroy(__logger); } diff --git a/src/launchpad-process-pool/src/launchpad_logger.c b/src/launchpad-process-pool/src/launchpad_logger.c deleted file mode 100644 index d6b99d8..0000000 --- a/src/launchpad-process-pool/src/launchpad_logger.c +++ /dev/null @@ -1,248 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "launchpad_config.h" -#include "launchpad_logger.h" -#include "log_private.h" - -#define LAUNCHPAD_LOG_APPFW_PATH "/var/log/appfw" -#define LAUNCHPAD_LOG_PATH "/var/log/appfw/launchpad" -#define LAUNCHPAD_LOG_MAX_SIZE 2500 -#define LAUNCHPAD_LOG_MAX_BUFFER_SIZE 256 - -struct logger_s { - int fd; - int index; -}; - -static int __set_smack_label(const char *path, const char *label) -{ - int ret; - - ret = smack_setlabel(path, label, SMACK_LABEL_ACCESS); - if (ret != 0) { - ret = -errno; - _E("smack_setlabel() is failed. path(%s), label(%s), errno(%d)", - path, label, errno); - return ret; - } - - return 0; -} - -static int __create_directory(const char *path) -{ - mode_t mode; - int ret; - - ret = access(path, F_OK); - if (ret == 0) - return 0; - - mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP; - ret = mkdir(path, mode); - if (ret < 0) { - ret = -errno; - _E("Failed to create directory(%s). errno(%d)", path, errno); - return ret; - } - - return 0; -} - -static int __create_launchpad_directories(void) -{ - const char *logger_path; - char path[PATH_MAX]; - int ret; - - logger_path = _config_get_string_value(CONFIG_TYPE_LOGGER_PATH); - ret = __create_directory(logger_path); - if (ret < 0) - return ret; - - ret = __set_smack_label(logger_path, "User::Home"); - if (ret < 0) - return ret; - - snprintf(path, sizeof(path), "%s/launchpad", logger_path); - ret = __create_directory(path); - if (ret < 0) - return ret; - - ret = __set_smack_label(path, "User"); - if (ret < 0) - return ret; - - return 0; -} - -int _logger_create(const char *path, logger_h *handle) -{ - struct logger_s *logger; - off_t offset; - int ret; - - if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) - return 0; - - if (!path || !handle) { - _E("Invalid parameter"); - return -EINVAL; - } - - ret = __create_launchpad_directories(); - if (ret < 0) - return ret; - - logger = calloc(1, sizeof(struct logger_s)); - if (!logger) { - _E("Out of memory"); - return -ENOMEM; - } - - logger->fd = open(path, O_CREAT | O_WRONLY, 0640); - if (logger->fd < 0) { - ret = -errno; - _E("Failed to open path(%s), errno(%d)", path, errno); - _logger_destroy(logger); - return ret; - } - - ret = __set_smack_label(path, "User"); - if (ret < 0) { - _logger_destroy(logger); - return ret; - } - - offset = lseek(logger->fd, 0, SEEK_END); - if (offset != 0) { - logger->index = (int)(offset / LAUNCHPAD_LOG_MAX_STRING_SIZE); - if (logger->index >= LAUNCHPAD_LOG_MAX_SIZE) { - logger->index = 0; - lseek(logger->fd, 0, SEEK_SET); - } - } - - *handle = logger; - - return 0; -} - -int _logger_destroy(logger_h handle) -{ - if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) - return 0; - - if (!handle) { - _E("Invalid parameter"); - return -EINVAL; - } - - if (handle->fd > 0) - close(handle->fd); - - free(handle); - - return 0; -} - -int _logger_print(logger_h handle, const char *tag, const char *format, ...) -{ - char buf[LAUNCHPAD_LOG_MAX_BUFFER_SIZE]; - char format_buf[128]; - struct tm tm = { 0, }; - time_t t; - ssize_t ret; - va_list ap; - off_t offset; - int bytes; - - if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) - return 0; - - if (!handle || !tag || !format) { - _E("Invalid parameter"); - return -EINVAL; - } - - t = time(NULL); - localtime_r(&t, &tm); - - if (handle->index != 0) - offset = lseek(handle->fd, 0, SEEK_CUR); - else - offset = lseek(handle->fd, 0, SEEK_SET); - - if (offset == -1) - _E("lseek() is failed. errno(%d)", errno); - - va_start(ap, format); - bytes = vsnprintf(format_buf, sizeof(format_buf), format, ap); - va_end(ap); - if (bytes < 0 || bytes >= sizeof(format_buf)) { - _E("vsnprintf() is failed. result(%d)", bytes); - return -1; - } - - snprintf(buf, sizeof(buf), - "[%6d] %04d-%02d-%02d %02d:%02d:%02d %-16s %-100s\n", - handle->index, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec, - tag, format_buf); - ret = write(handle->fd, buf, strlen(buf)); - if (ret < 0) { - ret = -errno; - _E("Failed to write log message. errno(%d)", errno); - return ret; - } - - if (++handle->index >= LAUNCHPAD_LOG_MAX_SIZE) - handle->index = 0; - - return ret; -} - -int _logger_get_fd(logger_h handle, int *fd) -{ - if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) - return 0; - - if (!handle || !fd) { - _E("Invalid parameter"); - return -EINVAL; - } - - *fd = handle->fd; - - return 0; -} diff --git a/src/launchpad-process-pool/src/launchpad_logger.cc b/src/launchpad-process-pool/src/launchpad_logger.cc new file mode 100644 index 0000000..592d73e --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_logger.cc @@ -0,0 +1,240 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "launchpad_config.h" +#include "launchpad_logger.h" +#include "log_private.h" + +#define LAUNCHPAD_LOG_APPFW_PATH "/var/log/appfw" +#define LAUNCHPAD_LOG_PATH "/var/log/appfw/launchpad" +#define LAUNCHPAD_LOG_MAX_SIZE 2500 +#define LAUNCHPAD_LOG_MAX_BUFFER_SIZE 256 + +struct logger_s { + int fd; + int index; +}; + +static int __set_smack_label(const char* path, const char* label) { + int ret; + + ret = smack_setlabel(path, label, SMACK_LABEL_ACCESS); + if (ret != 0) { + ret = -errno; + _E("smack_setlabel() is failed. path(%s), label(%s), errno(%d)", path, + label, errno); + return ret; + } + + return 0; +} + +static int __create_directory(const char* path) { + mode_t mode; + int ret; + + ret = access(path, F_OK); + if (ret == 0) + return 0; + + mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP; + ret = mkdir(path, mode); + if (ret < 0) { + ret = -errno; + _E("Failed to create directory(%s). errno(%d)", path, errno); + return ret; + } + + return 0; +} + +static int __create_launchpad_directories(void) { + const char* logger_path; + char path[PATH_MAX]; + int ret; + + logger_path = _config_get_string_value(CONFIG_TYPE_LOGGER_PATH); + ret = __create_directory(logger_path); + if (ret < 0) + return ret; + + ret = __set_smack_label(logger_path, "User::Home"); + if (ret < 0) + return ret; + + snprintf(path, sizeof(path), "%s/launchpad", logger_path); + ret = __create_directory(path); + if (ret < 0) + return ret; + + ret = __set_smack_label(path, "User"); + if (ret < 0) + return ret; + + return 0; +} + +int _logger_create(const char* path, logger_h* handle) { + struct logger_s* logger; + off_t offset; + int ret; + + if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) + return 0; + + if (!path || !handle) { + _E("Invalid parameter"); + return -EINVAL; + } + + ret = __create_launchpad_directories(); + if (ret < 0) + return ret; + + logger = static_cast(calloc(1, sizeof(struct logger_s))); + if (!logger) { + _E("Out of memory"); + return -ENOMEM; + } + + logger->fd = open(path, O_CREAT | O_WRONLY, 0640); + if (logger->fd < 0) { + ret = -errno; + _E("Failed to open path(%s), errno(%d)", path, errno); + _logger_destroy(logger); + return ret; + } + + ret = __set_smack_label(path, "User"); + if (ret < 0) { + _logger_destroy(logger); + return ret; + } + + offset = lseek(logger->fd, 0, SEEK_END); + if (offset != 0) { + logger->index = (int)(offset / LAUNCHPAD_LOG_MAX_STRING_SIZE); + if (logger->index >= LAUNCHPAD_LOG_MAX_SIZE) { + logger->index = 0; + lseek(logger->fd, 0, SEEK_SET); + } + } + + *handle = logger; + + return 0; +} + +int _logger_destroy(logger_h handle) { + if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) + return 0; + + if (!handle) { + _E("Invalid parameter"); + return -EINVAL; + } + + if (handle->fd > 0) + close(handle->fd); + + free(handle); + + return 0; +} + +int _logger_print(logger_h handle, const char* tag, const char* format, ...) { + char buf[LAUNCHPAD_LOG_MAX_BUFFER_SIZE]; + char format_buf[128]; + struct tm tm = { + 0, + }; + time_t t; + ssize_t ret; + va_list ap; + off_t offset; + int bytes; + + if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) + return 0; + + if (!handle || !tag || !format) { + _E("Invalid parameter"); + return -EINVAL; + } + + t = time(nullptr); + localtime_r(&t, &tm); + + if (handle->index != 0) + offset = lseek(handle->fd, 0, SEEK_CUR); + else + offset = lseek(handle->fd, 0, SEEK_SET); + + if (offset == -1) + _E("lseek() is failed. errno(%d)", errno); + + va_start(ap, format); + bytes = vsnprintf(format_buf, sizeof(format_buf), format, ap); + va_end(ap); + if (bytes < 0 || bytes >= sizeof(format_buf)) { + _E("vsnprintf() is failed. result(%d)", bytes); + return -1; + } + + snprintf(buf, sizeof(buf), + "[%6d] %04d-%02d-%02d %02d:%02d:%02d %-16s %-100s\n", handle->index, + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec, tag, format_buf); + ret = write(handle->fd, buf, strlen(buf)); + if (ret < 0) { + ret = -errno; + _E("Failed to write log message. errno(%d)", errno); + return ret; + } + + if (++handle->index >= LAUNCHPAD_LOG_MAX_SIZE) + handle->index = 0; + + return ret; +} + +int _logger_get_fd(logger_h handle, int* fd) { + if (!_config_get_int_value(CONFIG_TYPE_LOGGER_ENABLE)) + return 0; + + if (!handle || !fd) { + _E("Invalid parameter"); + return -EINVAL; + } + + *fd = handle->fd; + + return 0; +} diff --git a/src/launchpad-process-pool/src/launchpad_memory_monitor.c b/src/launchpad-process-pool/src/launchpad_memory_monitor.c deleted file mode 100644 index d4d4b2d..0000000 --- a/src/launchpad-process-pool/src/launchpad_memory_monitor.c +++ /dev/null @@ -1,151 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -#include "launchpad_config.h" -#include "launchpad_memory_monitor.h" -#include "launchpad_proc.h" -#include "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/src/launchpad_memory_monitor.cc b/src/launchpad-process-pool/src/launchpad_memory_monitor.cc new file mode 100644 index 0000000..d2b60ca --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_memory_monitor.cc @@ -0,0 +1,141 @@ +/* + * 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 +#include +#include +#include +#include + +#include "launchpad_config.h" +#include "launchpad_memory_monitor.h" +#include "launchpad_proc.h" +#include "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/src/launchpad_signal.c b/src/launchpad-process-pool/src/launchpad_signal.c deleted file mode 100644 index 6212ca4..0000000 --- a/src/launchpad-process-pool/src/launchpad_signal.c +++ /dev/null @@ -1,413 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "launchpad_common.h" -#include "launchpad_dbus.h" -#include "launchpad_io_channel.h" -#include "launchpad_proc.h" -#include "launchpad_signal.h" -#include "launchpad_socket.h" -#include "log_private.h" - -#define HYDRA_SIGCHLD_SOCK ".hydra-sigchld-sock" - -static pid_t __pid; -static sigset_t __mask; -static sigset_t __old_mask; -static socket_h __sigchld_socket; -static io_channel_h __sigchld_channel; -static socket_h __hydra_sigchld_socket; -static io_channel_h __hydra_sigchld_channel; -static signal_sigchld_cb __callback; -static void *__user_data; - -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 = NULL; - char path[PATH_MAX]; - - snprintf(path, sizeof(path), "/run/aul/apps/%d", getuid()); - dp = opendir(path); - if (!dp) - return; - - while ((dentry = readdir(dp)) != NULL) { - 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 __sigchld_action(int pid) -{ - _dbus_send_app_dead_signal(pid); - _delete_sock_path(pid, getuid()); - __socket_garbage_collector(); -} - -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, NULL); - 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; - io_condition_e cond; - 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); - - cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; - channel = _io_channel_create(fd, cond, - __hydra_sigchld_handler, NULL); - 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, NULL); - 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, NULL); - 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; - io_condition_e cond; - 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; - } - - cond = IO_IN | IO_PRI | IO_ERR | IO_HUP | IO_NVAL; - channel = _io_channel_create(sfd, cond, - __sigchld_handler, NULL); - 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; - } - } - - 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"); - _signal_set_sigchld_cb(NULL, NULL); - __hydra_sigchld_fini(); - __sigchld_fini(); - _signal_unblock_sigchld(); -} diff --git a/src/launchpad-process-pool/src/launchpad_signal.cc b/src/launchpad-process-pool/src/launchpad_signal.cc new file mode 100644 index 0000000..ca305b0 --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_signal.cc @@ -0,0 +1,395 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "launchpad_common.h" +#include "launchpad_dbus.h" +#include "launchpad_io_channel.h" +#include "launchpad_proc.h" +#include "launchpad_signal.h" +#include "launchpad_socket.h" +#include "log_private.h" + +#define HYDRA_SIGCHLD_SOCK ".hydra-sigchld-sock" + +static pid_t __pid; +static sigset_t __mask; +static sigset_t __old_mask; +static socket_h __sigchld_socket; +static io_channel_h __sigchld_channel; +static socket_h __hydra_sigchld_socket; +static io_channel_h __hydra_sigchld_channel; +static signal_sigchld_cb __callback; +static void* __user_data; + +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 __sigchld_action(int pid) { + _dbus_send_app_dead_signal(pid); + _delete_sock_path(pid, getuid()); + __socket_garbage_collector(); +} + +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; + } + } + + 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"); + _signal_set_sigchld_cb(nullptr, nullptr); + __hydra_sigchld_fini(); + __sigchld_fini(); + _signal_unblock_sigchld(); +} diff --git a/src/launchpad-process-pool/src/launchpad_worker.c b/src/launchpad-process-pool/src/launchpad_worker.c deleted file mode 100644 index 019e4a2..0000000 --- a/src/launchpad-process-pool/src/launchpad_worker.c +++ /dev/null @@ -1,186 +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. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "launchpad_worker.h" -#include "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 = malloc(sizeof(struct 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 = calloc(1, sizeof(struct 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/src/launchpad_worker.cc b/src/launchpad-process-pool/src/launchpad_worker.cc new file mode 100644 index 0000000..15b53a5 --- /dev/null +++ b/src/launchpad-process-pool/src/launchpad_worker.cc @@ -0,0 +1,179 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "launchpad_worker.h" +#include "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/src/loader_info.c b/src/launchpad-process-pool/src/loader_info.c deleted file mode 100644 index c43986f..0000000 --- a/src/launchpad-process-pool/src/loader_info.c +++ /dev/null @@ -1,609 +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. - */ -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#include "loader_info.h" -#include "launchpad_common.h" - -#define TAG_LOADER "[LOADER]" -#define TAG_NAME "NAME" -#define TAG_EXE "EXE" -#define TAG_APP_TYPE "APP_TYPE" -#define TAG_DETECTION_METHOD "DETECTION_METHOD" -#define TAG_ACTIVATION_METHOD "ACTIVATION_METHOD" -#define TAG_DEACTIVATION_METHOD "DEACTIVATION_METHOD" -#define TAG_TTL "TTL" -#define TAG_TIMEOUT "TIMEOUT" -#define TAG_EXTRA "EXTRA" -#define TAG_EXTRA_ARRAY "EXTRA_ARRAY" -#define TAG_EXTRA_ARRAY_VAL "EXTRA_ARRAY_VAL" -#define TAG_ALTERNATIVE_LOADER "ALTERNATIVE_LOADER" -#define TAG_HW_ACC "HW_ACC" -#define TAG_CPU_THRESHOLD_MAX "CPU_THRESHOLD_MAX" -#define TAG_CPU_THRESHOLD_MIN "CPU_THRESHOLD_MIN" -#define TAG_ON_BOOT "ON_BOOT" -#define TAG_HYDRA "HYDRA" -#define TAG_APP_CHECK "APP_CHECK" -#define TAG_ON_BOOT_TIMEOUT "ON_BOOT_TIMEOUT" -#define TAG_SCHED_PRIORITY "SCHED_PRIORITY" - -#define VAL_ON "ON" -#define VAL_OFF "OFF" -#define VAL_METHOD_TIMEOUT "TIMEOUT" -#define VAL_METHOD_DEMAND "DEMAND" -#define VAL_METHOD_VISIBILITY "VISIBILITY" -#define VAL_METHOD_REQUEST "REQUEST" -#define VAL_METHOD_AVAILABLE_MEMORY "AVAILABLE_MEMORY" -#define VAL_METHOD_TTL "TTL" -#define VAL_METHOD_OUT_OF_MEMORY "OUT_OF_MEMORY" - -static int __comp_name(gconstpointer a, gconstpointer b); -static void __free_info(gpointer data); - -static loader_info_t *__create_loader_info() -{ - loader_info_t *info; - - info = calloc(1, sizeof(loader_info_t)); - if (info == NULL) { - _E("Out of memory"); - return NULL; - } - - info->type = 0; - info->name = NULL; - info->exe = NULL; - info->app_types = NULL; - info->hw_acc = NULL; - info->alternative_loaders = NULL; - info->detection_method = METHOD_TIMEOUT | METHOD_VISIBILITY | - METHOD_INSTALL; - info->timeout_val = 5000; - info->extra = bundle_create(); - info->cpu_threshold_max = DEFAULT_CPU_THRESHOLD_MAX; - info->cpu_threshold_min = DEFAULT_CPU_THRESHOLD_MIN; - info->on_boot = true; - info->app_exists = false; - info->activation_method = 0; - info->deactivation_method = 0; - info->ttl = 600; /* 10 minutes */ - info->is_hydra = false; - info->app_check = true; - - return info; -} - -static void __parse_detection_method(loader_info_t *info, char *line) -{ - char *token; - char *savedptr; - - token = strtok_r(line, " |\t\r\n", &savedptr); - info->detection_method = 0; - while (token) { - if (!strcmp(token, VAL_METHOD_TIMEOUT)) - info->detection_method |= METHOD_TIMEOUT; - else if (!strcmp(token, VAL_METHOD_VISIBILITY)) - info->detection_method |= METHOD_VISIBILITY; - else if (!strcmp(token, VAL_METHOD_DEMAND)) - info->detection_method |= METHOD_DEMAND; - - token = strtok_r(NULL, " |\t\r\n", &savedptr); - } - - info->detection_method |= METHOD_INSTALL; - _D("detection_method:%d", info->detection_method); -} - -static void __parse_activation_method(loader_info_t *info, char *line) -{ - char *token; - char *savedptr; - - token = strtok_r(line, " |\t\r\n", &savedptr); - info->activation_method = 0; - while (token) { - if (!strcmp(token, VAL_METHOD_REQUEST)) - info->activation_method |= METHOD_REQUEST; - else if (!strcmp(token, VAL_METHOD_AVAILABLE_MEMORY)) - info->activation_method |= METHOD_AVAILABLE_MEMORY; - - token = strtok_r(NULL, " |\t\r\n", &savedptr); - } - - _D("activation_method:%d", info->activation_method); -} - -static void __parse_deactivation_method(loader_info_t *info, char *line) -{ - char *token; - char *savedptr; - - token = strtok_r(line, " |\t\r\n", &savedptr); - info->deactivation_method = 0; - while (token) { - if (!strcmp(token, VAL_METHOD_TTL)) - info->deactivation_method |= METHOD_TTL; - else if (!strcmp(token, VAL_METHOD_OUT_OF_MEMORY)) - info->deactivation_method |= METHOD_OUT_OF_MEMORY; - - token = strtok_r(NULL, " |\t\r\n", &savedptr); - } - - _D("deactivation_method:%d", info->deactivation_method); -} - -static void __parse_app_types(loader_info_t *info, char *line) -{ - char *token; - char *savedptr; - - token = strtok_r(line, " |\t\r\n", &savedptr); - while (token) { - info->app_types = g_list_append(info->app_types, strdup(token)); - token = strtok_r(NULL, " |\t\r\n", &savedptr); - } -} - -static void __parse_extra(loader_info_t *info, char *line) -{ - char *tok1 = NULL; - char *tok2 = NULL; - char *tok3 = NULL; - - if (info->extra == NULL) - return; - - sscanf(line, "%ms %ms %ms", &tok1, &tok2, &tok3); - - if (!tok1 || !tok2 || !tok3) - goto end; - - if (strlen(tok2) == 0 || strlen(tok3) == 0) - goto end; - - bundle_add_str(info->extra, tok2, tok3); - -end: - if (tok1) - free(tok1); - if (tok2) - free(tok2); - if (tok3) - free(tok3); -} - -static void __add_extra_array_from_list(bundle *b, const char *key, GList *list) -{ - const char **array; - int len; - int i; - GList *cur; - - if (b == NULL || key == NULL || list == NULL) - return; - - len = g_list_length(list); - array = malloc(sizeof(const char *) * len); - if (array == NULL) - return; - - cur = list; - for (i = 0; i < len; i++) { - array[i] = cur->data; - cur = g_list_next(cur); - } - - bundle_add_str_array(b, key, array, len); - free(array); -} - -static void __flush_extra_array(bundle *b, char *key, GList *list) -{ - if (list) { - __add_extra_array_from_list(b, key, list); - g_list_free_full(list, free); - } - - free(key); -} - -static GList *__parse_file(GList *list, const char *path) -{ - FILE *fp; - char buf[LINE_MAX]; - char *tok1 = NULL; - char *tok2 = NULL; - loader_info_t *cur_info = NULL; - char *key = NULL; - GList *extra_array = NULL; - - fp = fopen(path, "rt"); - if (fp == NULL) - return list; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - FREE_AND_NULL(tok1); - FREE_AND_NULL(tok2); - sscanf(buf, "%ms %ms", &tok1, &tok2); - if (tok1 && strcasecmp(TAG_LOADER, tok1) == 0) { - if (cur_info != NULL) { - __flush_extra_array(cur_info->extra, key, - extra_array); - extra_array = NULL; - key = NULL; - list = g_list_append(list, cur_info); - } - cur_info = __create_loader_info(); - if (!cur_info) - break; - continue; - } - - if (!tok1 || !tok2 || !cur_info) - continue; - if (tok1[0] == '\0' || tok2[0] == '\0' || tok1[0] == '#') - continue; - - if (strcasecmp(TAG_NAME, tok1) == 0) { - cur_info->name = strdup(tok2); - } else if (strcasecmp(TAG_EXE, tok1) == 0) { - cur_info->exe = strdup(tok2); - } else if (strcasecmp(TAG_APP_TYPE, tok1) == 0) { - __parse_app_types(cur_info, &buf[strlen(tok1)]); - } else if (strcasecmp(TAG_DETECTION_METHOD, tok1) == 0) { - __parse_detection_method(cur_info, &buf[strlen(tok1)]); - } else if (strcasecmp(TAG_ACTIVATION_METHOD, tok1) == 0) { - __parse_activation_method(cur_info, - &buf[strlen(tok1)]); - } else if (strcasecmp(TAG_DEACTIVATION_METHOD, tok1) == 0) { - __parse_deactivation_method(cur_info, - &buf[strlen(tok1)]); - } else if (strcasecmp(TAG_TTL, tok1) == 0) { - cur_info->ttl = strtoul(tok2, NULL, 10); - } else if (strcasecmp(TAG_TIMEOUT, tok1) == 0) { - cur_info->timeout_val = atoi(tok2); - } else if (strcasecmp(TAG_EXTRA, tok1) == 0) { - __parse_extra(cur_info, buf); - } else if (strcasecmp(TAG_EXTRA_ARRAY, tok1) == 0) { - __flush_extra_array(cur_info->extra, key, extra_array); - extra_array = NULL; - key = strdup(tok2); - } else if (strcasecmp(TAG_EXTRA_ARRAY_VAL, tok1) == 0) { - extra_array = g_list_append(extra_array, strdup(tok2)); - } else if (strcasecmp(TAG_HW_ACC, tok1) == 0) { - cur_info->hw_acc = strdup(tok2); - } else if (strcasecmp(TAG_ALTERNATIVE_LOADER, tok1) == 0) { - cur_info->alternative_loaders = - g_list_append(cur_info->alternative_loaders, - strdup(tok2)); - } else if (strcasecmp(TAG_CPU_THRESHOLD_MAX, tok1) == 0) { - cur_info->cpu_threshold_max = atoi(tok2); - } else if (strcasecmp(TAG_CPU_THRESHOLD_MIN, tok1) == 0) { - cur_info->cpu_threshold_min = atoi(tok2); - } else if (strcasecmp(TAG_ON_BOOT, tok1) == 0) { - if (tok2 && strcasecmp(VAL_OFF, tok2) == 0) - cur_info->on_boot = false; - } else if (strcasecmp(TAG_HYDRA, tok1) == 0) { - if (strcasecmp(VAL_ON, tok2) == 0) - cur_info->is_hydra = 1; - else - cur_info->is_hydra = 0; - } else if (strcasecmp(TAG_APP_CHECK, tok1) == 0) { - if (tok2 && strcasecmp(VAL_OFF, tok2) == 0) - cur_info->app_check = false; - } else if (strcasecmp(TAG_ON_BOOT_TIMEOUT, tok1) == 0) { - cur_info->on_boot_timeout = atoi(tok2); - } else if (strcasecmp(TAG_SCHED_PRIORITY, tok1) == 0) { - cur_info->sched_priority = atoi(tok2); - if (cur_info->sched_priority < -20) - cur_info->sched_priority = -20; - else if (cur_info->sched_priority > 19) - cur_info->sched_priority = 19; - } - } - - if (cur_info != NULL) { - __flush_extra_array(cur_info->extra, key, extra_array); - list = g_list_append(list, cur_info); - } - - if (tok1) - free(tok1); - if (tok2) - free(tok2); - - fclose(fp); - - return list; -} - -GList *_loader_info_load_dir(const char *path) -{ - DIR *dir_info; - struct dirent *entry = NULL; - GList *list = NULL; - char buf[PATH_MAX]; - char *ext; - - dir_info = opendir(path); - if (dir_info == NULL) - return NULL; - - while ((entry = readdir(dir_info)) != NULL) { - if (entry->d_name[0] == '.') - continue; - ext = strrchr(entry->d_name, '.'); - if (ext && !strcmp(ext, ".loader")) { - snprintf(buf, sizeof(buf), "%s/%s", path, entry->d_name); - list = __parse_file(list, buf); - } - } - closedir(dir_info); - - return list; -} - -GList *_loader_info_load_file(GList *list, const char *path) -{ - return __parse_file(list, path); -} - -GList *_loader_info_unload(GList *list, const char *loader_name) -{ - GList *cur; - loader_info_t *info; - - cur = g_list_find_custom(list, loader_name, __comp_name); - if (cur == NULL) - return list; - - info = cur->data; - - list = g_list_remove(list, info); - __free_info(info); - - return list; -} - -const char* _loader_info_find_loader_path_by_loader_name(GList *list, const char *loader_name) -{ - GList *cur; - loader_info_t *info; - - cur = g_list_find_custom(list, loader_name, __comp_name); - if (cur == NULL) - return NULL; - - info = cur->data; - - return info->exe; -} - -loader_info_t* _loader_info_find_loader_by_loader_name(GList *list, const char *loader_name) -{ - GList *cur; - loader_info_t *info; - - cur = g_list_find_custom(list, loader_name, __comp_name); - if (cur == NULL) - return NULL; - - info = cur->data; - - return info; -} - -static void __free_info(gpointer data) -{ - loader_info_t *info; - - if (data == NULL) - return; - - info = (loader_info_t *)data; - - free(info->name); - free(info->exe); - if (info->app_types) - g_list_free_full(info->app_types, free); - free(info->hw_acc); - if (info->extra) - bundle_free(info->extra); - if (info->alternative_loaders) - g_list_free_full(info->alternative_loaders, free); - - free(info); -} - -void _loader_info_dispose(GList *info) -{ - g_list_free_full(info, __free_info); -} - -static int __comp_str(gconstpointer a, gconstpointer b) -{ - if (!a || !b) - return -1; - return strcmp(a, b); -} - -static int __comp_app_type_with_hw_acc(gconstpointer a, gconstpointer b) -{ - loader_info_t *info = (loader_info_t *)a; - - if (info == NULL || info->app_types == NULL || b == NULL) - return -1; - - if (g_list_find_custom(info->app_types, b, __comp_str) && - (info->hw_acc == NULL || !strcasecmp(VAL_ON, info->hw_acc))) - return 0; - - return -1; -} - -static int __comp_app_type_with_sw_acc(gconstpointer a, gconstpointer b) -{ - loader_info_t *info = (loader_info_t *)a; - - if (info == NULL || info->app_types == NULL || b == NULL) - return -1; - - if (g_list_find_custom(info->app_types, b, __comp_str) && - (info->hw_acc == NULL || !strcasecmp(VAL_OFF, info->hw_acc))) - return 0; - - return -1; -} - -static int __comp_name(gconstpointer a, gconstpointer b) -{ - loader_info_t *info = (loader_info_t *)a; - - if (info == NULL || info->name == NULL || b == NULL) - return -1; - - return strcmp(info->name, b); -} - -int _loader_info_find_type(GList *info, const char *app_type, bool hwacc) -{ - GList *cur; - - if (hwacc) { - cur = g_list_find_custom(info, app_type, - __comp_app_type_with_hw_acc); - } else { - cur = g_list_find_custom(info, app_type, - __comp_app_type_with_sw_acc); - } - - if (cur == NULL) - return -1; - - loader_info_t *cur_info = (loader_info_t *)cur->data; - - return cur_info->type; -} - -int _loader_info_find_type_by_loader_name(GList *info, const char *loader_name) -{ - GList *cur = NULL; - - cur = g_list_find_custom(info, loader_name, __comp_name); - if (cur == NULL) - return -1; - - loader_info_t *cur_info = (loader_info_t *)cur->data; - - return cur_info->type; -} - -static int *__make_type_array(GList *info, GList *loaders, int *len) -{ - int l; - int *t; - loader_info_t *i; - GList *c; - GList *cur; - int j = 0; - - l = g_list_length(loaders); - - if (l <= 0) - return NULL; - - t = malloc(sizeof(int) * l); - if (!t) - return NULL; - - *len = l; - - cur = loaders; - while (cur) { - c = g_list_find_custom(info, cur->data, __comp_name); - - if (c) { - i = (loader_info_t *)c->data; - t[j] = i->type; - j++; - } - - cur = g_list_next(cur); - } - - return t; -} - -int *_loader_get_alternative_types(GList *info, int type, int *len) -{ - GList *cur; - loader_info_t *i; - - if (!info) - return NULL; - - cur = info; - while (cur) { - i = (loader_info_t *)cur->data; - if (i->type == type) { - if (!i->alternative_loaders) - return NULL; - - return __make_type_array(info, i->alternative_loaders, - len); - } - cur = g_list_next(cur); - } - - return NULL; -} - -int _loader_info_foreach(GList *info, loader_info_foreach_cb callback, - void *data) -{ - GList *cur; - loader_info_t *i; - - if (!info || !callback) - return -1; - - cur = info; - while (cur) { - i = (loader_info_t *)cur->data; - callback(i, data); - cur = g_list_next(cur); - } - - return 0; -} - -bool _loader_info_exist_app_type(loader_info_t *info, const char *app_type) -{ - GList *list; - - list = g_list_find_custom(info->app_types, app_type, __comp_str); - if (list) - return true; - - return false; -} diff --git a/src/launchpad-process-pool/src/loader_info.cc b/src/launchpad-process-pool/src/loader_info.cc new file mode 100644 index 0000000..548dfe1 --- /dev/null +++ b/src/launchpad-process-pool/src/loader_info.cc @@ -0,0 +1,452 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "launchpad_common.h" +#include "loader_info.hh" +#include "util.hh" + +namespace launchpad { +namespace { + +constexpr const char kTagLoader[] = "[LOADER]"; +constexpr const char kTagName[] = "NAME"; +constexpr const char kTagExe[] = "EXE"; +constexpr const char kTagAppType[] = "APP_TYPE"; +constexpr const char kTagDetectionMethod[] = "DETECTION_METHOD"; +constexpr const char kTagActivationMethod[] = "ACTIVATION_METHOD"; +constexpr const char kTagDeactivationMethod[] = "DEACTIVATION_METHOD"; +constexpr const char kTagTtl[] = "TTL"; +constexpr const char kTagTimeout[] = "TIMEOUT"; +constexpr const char kTagExtra[] = "EXTRA"; +constexpr const char kTagExtraArray[] = "EXTRA_ARRAY"; +constexpr const char kTagExtraArrayVal[] = "EXTRA_ARRAY_VAL"; +constexpr const char kTagAlternativeLoader[] = "ALTERNATIVE_LOADER"; +constexpr const char kTagHwAcc[] = "HW_ACC"; +constexpr const char kTagCpuThresholdMax[] = "CPU_THRESHOLD_MAX"; +constexpr const char kTagCpuThresholdMin[] = "CPU_THRESHOLD_MIN"; +constexpr const char kTagOnBoot[] = "ON_BOOT"; +constexpr const char kTagHydra[] = "HYDRA"; +constexpr const char kTagAppCheck[] = "APP_CHECK"; +constexpr const char kTagOnBootTimeout[] = "ON_BOOT_TIMEOUT"; +constexpr const char kTagSchedPriority[] = "SCHED_PRIORITY"; + +constexpr const char kValOn[] = "ON"; +constexpr const char kValOff[] = "OFF"; +constexpr const char kValMethodTimeout[] = "TIMEOUT"; +constexpr const char kValMethodDemand[] = "DEMAND"; +constexpr const char kValMethodVisibility[] = "VISIBILITY"; +constexpr const char kValMethodRequest[] = "REQUEST"; +constexpr const char kValMethodAvailableMemory[] = "AVAILABLE_MEMORY"; +constexpr const char kValMethodTtl[] = "TTL"; +constexpr const char kValMethodOutOfMemory[] = "OUT_OF_MEMORY"; + +} // namespace + +namespace fs = std::filesystem; + +void LoaderInfoInflator::ParseDetectionMethod(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss) { + std::string line = tok_start; + do { + auto tokens = Split(line, " |\t\r\n"); + for (auto& token : tokens) { + if (token == kValMethodTimeout) + info->detection_method_ = + info->detection_method_ | LoaderMethod::Timeout; + else if (token == kValMethodVisibility) + info->detection_method_ = + info->detection_method_ | LoaderMethod::Visibility; + else if (token == kValMethodDemand) + info->detection_method_ = + info->detection_method_ | LoaderMethod::Demand; + } + } while (std::getline(ss, line)); + + info->detection_method_ = info->detection_method_ | LoaderMethod::Install; + _D("detection_method:%d", static_cast(info->detection_method_)); +} + +void LoaderInfoInflator::ParseActivationMethod(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss) { + info->activation_method_ = LoaderMethod::Empty; + std::string line = tok_start; + do { + auto tokens = Split(line, " |\t\r\n"); + for (auto& token : tokens) { + if (token == kValMethodRequest) + info->activation_method_ = + info->activation_method_ | LoaderMethod::Request; + else if (token == kValMethodAvailableMemory) + info->activation_method_ = + info->activation_method_ | LoaderMethod::AvailableMemory; + } + } while (std::getline(ss, line)); + + _D("activation_method:%d", static_cast(info->activation_method_)); +} + +void LoaderInfoInflator::ParseDeactivationMethod(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss) { + info->deactivation_method_ = LoaderMethod::Empty; + std::string line = tok_start; + do { + auto tokens = Split(line, " |\t\r\n"); + for (auto& token : tokens) { + if (token == kValMethodTtl) + info->deactivation_method_ = + info->deactivation_method_ | LoaderMethod::Ttl; + else if (token == kValMethodOutOfMemory) + info->deactivation_method_ = + info->deactivation_method_ | LoaderMethod::OutOfMemory; + } + } while (std::getline(ss, line)); + + _D("deactivation_method:%d", static_cast(info->deactivation_method_)); +} + +void LoaderInfoInflator::ParseAppTypes(const LoaderInfoPtr& info, + std::string& tok_start, + std::istringstream& ss) { + std::string line = tok_start; + do { + auto tokens = Split(line, " |\t\r\n"); + for (auto& token : tokens) { + info->app_types_.push_back(std::move(token)); + } + } while (std::getline(ss, line)); +} + +void LoaderInfoInflator::Parse(std::vector& loader_info_list, + const fs::path& path) { + std::ifstream fp; + fp.open(path); + if (fp.fail()) + return; + + LoaderInfoPtr info; + std::string input; + std::string extra_array_key; + std::vector extra_array; + while (std::getline(fp, input)) { + std::istringstream ss(input); + std::string tok1, tok2; + if (!(ss >> tok1)) + continue; + + if (strcasecmp(kTagLoader, tok1.c_str()) == 0) { + if (info != nullptr) { + if (!extra_array.empty()) { + info->extra_.Add(std::move(extra_array_key), std::move(extra_array)); + extra_array.clear(); + } + + loader_info_list.push_back(std::move(info)); + } + + info = std::make_shared(); + 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) { + info->exe_ = std::move(tok2); + } else if (kTagAppType == key) { + ParseAppTypes(info, tok2, ss); + } else if (kTagDetectionMethod == key) { + ParseDetectionMethod(info, tok2, ss); + } else if (kTagActivationMethod == key) { + ParseActivationMethod(info, tok2, ss); + } else if (kTagDeactivationMethod == key) { + ParseDeactivationMethod(info, tok2, ss); + } else if (kTagTtl == key) { + info->ttl_ = std::stoul(tok2); + } else if (kTagTimeout == key) { + info->timeout_val_ = std::stoi(tok2); + } else if (kTagExtra == key) { + std::string val; + if (ss >> val) + info->extra_.Add(std::move(tok2), std::move(val)); + } else if (kTagExtraArray == key) { + if (!extra_array.empty()) { + info->extra_.Add(std::move(extra_array_key), std::move(extra_array)); + extra_array.clear(); + } + extra_array_key = std::move(tok2); + } else if (kTagExtraArrayVal == key) { + extra_array.push_back(std::move(tok2)); + } else if (kTagHwAcc == key) { + info->hw_acc_ = std::move(tok2); + } else if (kTagAlternativeLoader == key) { + info->alternative_loaders_.push_back(std::move(tok2)); + } else if (kTagCpuThresholdMax == key) { + info->cpu_threshold_max_ = std::stoi(tok2); + } else if (kTagCpuThresholdMin == key) { + info->cpu_threshold_min_ = std::stoi(tok2); + } else if (kTagOnBoot == key) { + if (kValOff == tok2) + info->on_boot_ = false; + } else if (kTagHydra == key) { + if (kValOn == tok2) + info->is_hydra_ = true; + else + info->is_hydra_ = false; + } else if (kTagAppCheck == key) { + if (kValOff == tok2) + info->app_check_ = false; + } else if (kTagOnBootTimeout == key) { + info->on_boot_timeout_ = std::stoi(tok2); + } else if (kTagSchedPriority == key) { + info->sched_priority_ = std::min(std::max(std::stoi(tok2), -20), 19); + } + } + + fp.close(); + if (info != nullptr) { + if (!extra_array.empty()) + info->extra_.Add(std::move(extra_array_key), std::move(extra_array)); + + loader_info_list.push_back(std::move(info)); + } +} + +LoaderType LoaderInfo::GetType() const { + return type_; +} + +const std::string& LoaderInfo::GetName() const { + return name_; +} + +const std::string& LoaderInfo::GetExe() const { + return exe_; +} + +int LoaderInfo::GetCpuThresholdMax() const { + return cpu_threshold_max_; +} + +int LoaderInfo::GetCpuThresholdMin() const { + return cpu_threshold_min_; +} + +unsigned int LoaderInfo::GetTtl() const { + return ttl_; +} + +const std::vector& LoaderInfo::GetAppTypes() const { + return app_types_; +} + +LoaderMethod LoaderInfo::GetDetectionMethod() const { + return detection_method_; +} + +LoaderMethod LoaderInfo::GetActivationMethod() const { + return activation_method_; +} + +LoaderMethod LoaderInfo::GetDeactivationMethod() const { + return deactivation_method_; +} + +const std::string& LoaderInfo::GetHwAcc() const { + return hw_acc_; +} + +int LoaderInfo::GetOnbootTimeout() const { + return on_boot_timeout_; +} + +int LoaderInfo::GetTimeoutVal() const { + return timeout_val_; +} + +int LoaderInfo::GetSchedPriority() const { + return sched_priority_; +} + +bool LoaderInfo::IsAppExists() const { + return app_exists_; +} + +bool LoaderInfo::IsOnBoot() const { + return on_boot_; +} + +bool LoaderInfo::IsHydraEnabled() const { + return is_hydra_; +} + +bool LoaderInfo::IsNeededAppCheck() const { + return app_check_; +} + +tizen_base::Bundle& LoaderInfo::GetExtra() { + return extra_; +} + +void LoaderInfo::SetType(LoaderType type) { + type_ = type; +} + +void LoaderInfo::SetAppExists(bool exists) { + app_exists_ = exists; +} + +std::vector LoaderInfoInflator::Inflate( + const std::string_view path) { + fs::path p(path); + if (fs::is_directory(p) == false) + return {}; + + std::vector result; + for (auto& entry : fs::directory_iterator(p)) { + fs::path file(entry.path()); + if (file.extension() == ".loader") + Parse(result, file); + } + + return result; +} + +LoaderInfoManager::LoaderInfoManager(std::string path): path_(std::move(path)) { + +} + +void LoaderInfoManager::Load() { + if (!loader_list_.empty()) + return; + + LoaderInfoInflator inflator; + loader_list_ = inflator.Inflate(path_); +} + +void LoaderInfoManager::LoadFile(const std::string_view file) { + LoaderInfoInflator inflator; + fs::path p(path_); + inflator.Parse(loader_list_, p / file); +} + +void LoaderInfoManager::Unload(const std::string_view loader_name) { + loader_list_.erase(std::remove_if(loader_list_.begin(), loader_list_.end(), + [&](const LoaderInfoPtr& info) -> bool { + return info->GetName() == loader_name; + }), loader_list_.end()); +} + +void LoaderInfoManager::Dispose() { + loader_list_.clear(); +} + +std::string LoaderInfoManager::FindLoaderPath( + const std::string_view loader_name) { + for (auto& info : loader_list_) { + if (info->GetName() == loader_name) + return info->GetExe(); + } + + return ""; +} + +LoaderInfoPtr LoaderInfoManager::FindLoaderInfo( + const std::string_view loader_name) { + for (auto& info : loader_list_) { + if (info->GetName() == loader_name) + return info; + } + + return nullptr; +} + +LoaderType LoaderInfoManager::FindHwType(const std::string_view app_type) { + for (auto& info : loader_list_) { + if (info->GetHwAcc().empty() || info->GetHwAcc() == kValOn) { + auto it = std::find_if( + info->GetAppTypes().begin(), info->GetAppTypes().end(), + [&](const std::string& type) -> bool { return type == app_type; }); + + if (it != info->GetAppTypes().end()) + return info->GetType(); + } + } + + return LoaderType::Unsupported; +} + +LoaderType LoaderInfoManager::FindSwType(const std::string_view app_type) { + for (auto& info : loader_list_) { + if (info->GetHwAcc().empty() || info->GetHwAcc() == kValOff) { + auto it = std::find_if( + info->GetAppTypes().begin(), info->GetAppTypes().end(), + [&](const std::string& type) -> bool { return type == app_type; }); + + if (it != info->GetAppTypes().end()) + return info->GetType(); + } + } + + return LoaderType::Unsupported; +} + +std::vector LoaderInfoManager::GetAlternativeTypes( + LoaderType type) { + std::vector result; + for (auto& info : loader_list_) { + if (info->GetType() == type) { + for (auto& alt_loader : info->alternative_loaders_) { + auto it = std::find_if(loader_list_.begin(), loader_list_.end(), + [&](const auto& li) -> bool { + return li->GetName() == alt_loader; + }); + + if (it != loader_list_.end()) { + result.push_back((*it)->GetType()); + } + } + } + } + + return result; +} + +const std::vector& LoaderInfoManager::GetLoaderInfoList() const { + return loader_list_; +} + +} // namespace launchpad diff --git a/src/launchpad-process-pool/inc/launcher_info.h b/src/launchpad-process-pool/src/util.cc similarity index 52% rename from src/launchpad-process-pool/inc/launcher_info.h rename to src/launchpad-process-pool/src/util.cc index c8a470b..172d1bd 100644 --- a/src/launchpad-process-pool/inc/launcher_info.h +++ b/src/launchpad-process-pool/src/util.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 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,17 +14,22 @@ * limitations under the License. */ -#ifndef __LAUNCHER_INFO_H__ -#define __LAUNCHER_INFO_H__ +#include "util.hh" -#include +#include -typedef struct launcher_info_s *launcher_info_h; +namespace launchpad { -GList *_launcher_info_load(const char *path); -void _launcher_info_unload(GList *info); -launcher_info_h _launcher_info_find(GList *info_list, const char *app_type); -const char *_launcher_info_get_exe(launcher_info_h launcher_info); -GList *_launcher_info_get_extra_args(launcher_info_h launcher_info); +std::vector Split(const std::string& str, + 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) { + result.push_back((*i).str()); + } -#endif /* __LAUNCHER_INFO_H__ */ + return result; +} + +} // namespace launchpad diff --git a/src/lib/common/inc/launchpad_plugin.h b/src/lib/common/inc/launchpad_plugin.h index f2cf987..d8b7123 100644 --- a/src/lib/common/inc/launchpad_plugin.h +++ b/src/lib/common/inc/launchpad_plugin.h @@ -19,6 +19,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + int _launchpad_plugin_prepare_app(const char *app_id, bundle *kb); +#ifdef __cplusplus +} +#endif + #endif /* __LAUNCHPAD_PLUGIN_H__ */ -- 2.7.4 From 89fcb5d273fcdafdaae7f3695eae748cf7e25022 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Tue, 7 Feb 2023 18:37:48 +0900 Subject: [PATCH 12/16] Add unittest Unittest adds: - DebuggerInfo - LauncherInfo - LoaderInfo Change-Id: If2a8bf0ea367eb071713d951ba6117f83a5765bd Signed-off-by: Changgyu Choi --- CMakeLists.txt | 9 +- packaging/launchpad.spec | 13 +- tests/CMakeLists.txt | 1 + .../launchpad-process-pool-unittest/CMakeLists.txt | 51 +++++ .../src/test_launchpad.cc | 236 +++++++++++++++++++++ .../src/test_main.cc | 42 ++++ 6 files changed, 350 insertions(+), 2 deletions(-) create mode 100644 tests/CMakeLists.txt create mode 100644 tests/launchpad-process-pool-unittest/CMakeLists.txt create mode 100644 tests/launchpad-process-pool-unittest/src/test_launchpad.cc create mode 100644 tests/launchpad-process-pool-unittest/src/test_main.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 7c79e5f..02e8130 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) PROJECT(launchpad) IF(_TIZEN_FEATURE_PRIORITY_CHANGE) @@ -68,5 +68,12 @@ PKG_CHECK_MODULES(SECURITY_MANAGER_DEPS REQUIRED security-manager) PKG_CHECK_MODULES(TANCHOR_DEPS REQUIRED tanchor) PKG_CHECK_MODULES(TTRACE_DEPS REQUIRED ttrace) PKG_CHECK_MODULES(VCONF_DEPS REQUIRED vconf) +PKG_CHECK_MODULES(GMOCK_DEPS REQUIRED gmock) + +ENABLE_TESTING() +SET(LAUNCHPAD_PROCESS_POOL_UNITTEST launchpad-process-pool-unittest) +ADD_TEST(NAME ${LAUNCHPAD_PROCESS_POOL_UNITTEST} COMMAND ${LAUNCHPAD_PROCESS_POOL_UNITTEST} + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/launchpad-process-pool-unittest) ADD_SUBDIRECTORY(src) +ADD_SUBDIRECTORY(tests) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 070f3d7..413133e 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -33,6 +33,7 @@ BuildRequires: pkgconfig(iniparser) BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(libsmack) BuildRequires: pkgconfig(pkgmgr-installer) +BuildRequires: pkgconfig(gmock) Requires(post): /sbin/ldconfig Requires(post): /usr/bin/systemctl @@ -41,7 +42,6 @@ Requires(postun): /usr/bin/systemctl Requires(preun): /usr/bin/systemctl Provides: app-launchpad -Obsoletes: amd-mod-launchpad %define tizen_feature_priority_change 0 %ifarch armv7l i686 i586 @@ -102,6 +102,12 @@ Requires: liblaunchpad = %{version}-%{release} %description -n liblaunchpad-devel Launchpad library (devel) +%package unittests +Summary: %{name} unittests binary + +%description unittests +unittests binary + %prep %setup -q cp %{SOURCE1001} . @@ -144,6 +150,9 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` . %__make %{?_smp_mflags} +%check +ctest --verbose %{?_smp_mflags} + %install rm -rf %{buildroot} @@ -200,3 +209,5 @@ ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.targ %{_libdir}/pkgconfig/liblaunchpad.pc %{_libdir}/pkgconfig/liblaunchpad-hydra.pc +%files unittests +%{_bindir}/launchpad-process-pool-unittest diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..adf695a --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1 @@ +ADD_SUBDIRECTORY(launchpad-process-pool-unittest) diff --git a/tests/launchpad-process-pool-unittest/CMakeLists.txt b/tests/launchpad-process-pool-unittest/CMakeLists.txt new file mode 100644 index 0000000..c79c682 --- /dev/null +++ b/tests/launchpad-process-pool-unittest/CMakeLists.txt @@ -0,0 +1,51 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12) +PROJECT(launchpad-process-pool-unittest C CXX) + +INCLUDE(FindPkgConfig) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Winline") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++17 -DUNIT_TEST") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/common/inc) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/inc) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src UNITTESTS_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/common/src LAUNCHPAD_COMMON_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/src LAUNCHPAD_PROCESS_POOL_SOURCES) +LIST(REMOVE_ITEM LAUNCHPAD_PROCESS_POOL_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/src/launchpad.cc" +) + +ADD_EXECUTABLE(${PROJECT_NAME} + ${LAUNCHPAD_PROCESS_POOL_SOURCES} + ${LAUNCHPAD_COMMON_SOURCES} + ${UNITTESTS_SOURCES} +) + +APPLY_PKG_CONFIG(${PROJECT_NAME} PUBLIC + BUNDLE_DEPS + DBUS_DEPS + DLOG_DEPS + DLOG_REDIRECT_STDOUT_DEPS + GIO_DEPS + INIPARSER_DEPS + LIBCAP_DEPS + LIBSMACK_DEPS + LIBSYSTEMD_DEPS + LIBTZPLATFORM_CONFIG_DEPS + SECURITY_MANAGER_DEPS + TANCHOR_DEPS + TTRACE_DEPS + VCONF_DEPS + GMOCK_DEPS +) + +SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "${EXTRA_CFLAGS}") +TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE "-ldl") + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION /usr/bin/) diff --git a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc new file mode 100644 index 0000000..ad9e83e --- /dev/null +++ b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc @@ -0,0 +1,236 @@ +/* + * 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 +#include +#include +#include +#include + +#include +#include + +#include "debugger_info.hh" +#include "launcher_info.hh" +#include "loader_info.hh" + +using ::testing::AtLeast; +using namespace launchpad; + +class LaunchpadTest : public ::testing::Test { + public: + virtual void SetUp() { + std::ofstream of; + of.open(test_debugger); + of << test_debugger; + of.close(); + + of.open(test_launcher); + of << test_launcher; + of.close(); + + of.open(test_loader); + of << test_loader; + of.close(); + + of.open(test_debugger_info_file); + of << R"__test( +[DEBUGGER] +NAME DEBUG +EXE test_debugger +APP_TYPE capp|c++app +EXTRA_KEY __DLP_DEBUG_ARG__ +DEFAULT_OPT --wrapper +DEFAULT_OPT env +DEFAULT_OPT OPENSSL_armcap=0 +DEFAULT_OPT -- +)__test"; + of.close(); + + of.open(test_launcher_info_file); + of << R"__test( +[LAUNCHER] +NAME dotnet-launcher +EXE test_launcher +APP_TYPE dotnet +EXTRA_ARG --PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE +EXTRA_ARG --profile +EXTRA_ARG --appType +EXTRA_ARG dotnet +EXTRA_ARG TIZEN_UIFW +EXTRA_ARG ElmSharp +EXTRA_ARG --standalone +)__test"; + of.close(); + + of.open(test_loader_info_file); + of << R"__test( +[LOADER] +NAME hw-loader1 +EXE /usr/bin/launchpad-loader +APP_TYPE capp|c++app +HW_ACC ON +DETECTION_METHOD TIMEOUT|VISIBILITY +TIMEOUT 5000 +EXTRA loader_type hw-loader +EXTRA_ARRAY preload +EXTRA_ARRAY_VAL /usr/lib/libappcore-efl.so.1 +EXTRA_ARRAY_VAL /usr/lib/libappcore-common.so.1 +EXTRA_ARRAY_VAL /usr/lib/libcapi-appfw-application.so.0 +EXTRA_ARRAY_VAL /usr/lib/ecore_imf/modules/wayland/v-1.25/module.so +EXTRA_ARRAY_VAL /usr/lib/libdali-toolkit.so +EXTRA_ARRAY_VAL /usr/lib/libcairo.so.2 +EXTRA_ARRAY_VAL /usr/lib/libcapi-media-player.so.0 +EXTRA_ARRAY_VAL /usr/lib/libcapi-media-camera.so.0 +EXTRA_ARRAY_VAL /usr/lib/ecore_evas/engines/extn/v-1.25/module.so +ALTERNATIVE_LOADER common-loader1 +EXTRA threads 7 + +)__test"; + of.close(); + } + + virtual void TearDown() {} + + private: + const std::string test_debugger = "test_debugger"; + const std::string test_launcher = "test_launcher"; + const std::string test_loader = "test_loader"; + const std::string test_debugger_info_file = "test.debugger"; + const std::string test_launcher_info_file = "test.launcher"; + const std::string test_loader_info_file = "test.loader"; +}; + +TEST_F(LaunchpadTest, DebuggerInfoTest) { + /* Test debugger info file + [DEBUGGER] + NAME DEBUG + EXE test_debugger + APP_TYPE capp|c++app + EXTRA_KEY __DLP_DEBUG_ARG__ + DEFAULT_OPT --wrapper + DEFAULT_OPT env + DEFAULT_OPT OPENSSL_armcap=0 + DEFAULT_OPT -- + */ + + DebuggerInfoInflator inflator; + auto list = inflator.Inflate("."); + EXPECT_EQ(list.size(), 1); + auto info = std::move(list.front()); + EXPECT_EQ(info->GetName(), "DEBUG"); + EXPECT_EQ(info->GetExe(), "test_debugger"); + EXPECT_EQ(info->GetAppTypes().size(), 2); + EXPECT_EQ(info->GetAppTypes()[0], "capp"); + EXPECT_EQ(info->GetAppTypes()[1], "c++app"); + EXPECT_EQ(info->GetExtraKeyList().size(), 1); + EXPECT_EQ(info->GetExtraKeyList()[0], "__DLP_DEBUG_ARG__"); + EXPECT_EQ(info->GetDefaultOptList().size(), 4); + EXPECT_EQ(info->GetDefaultOptList()[0], "--wrapper"); + EXPECT_EQ(info->GetDefaultOptList()[1], "env"); + EXPECT_EQ(info->GetDefaultOptList()[2], "OPENSSL_armcap=0"); + EXPECT_EQ(info->GetDefaultOptList()[3], "--"); +} + +TEST_F(LaunchpadTest, LauncherInfoTest) { + /* Test launcher info file + [LAUNCHER] + NAME dotnet-launcher + EXE test_launcher + APP_TYPE dotnet + EXTRA_ARG + --PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE + EXTRA_ARG --profile + EXTRA_ARG --appType + EXTRA_ARG dotnet + EXTRA_ARG TIZEN_UIFW + EXTRA_ARG ElmSharp + EXTRA_ARG --standalone + */ + + LauncherInfoInflator inflator; + auto list = inflator.Inflate("."); + EXPECT_EQ(list.size(), 1); + auto info = std::move(list.front()); + EXPECT_EQ(info->GetName(), "dotnet-launcher"); + EXPECT_EQ(info->GetExe(), "test_launcher"); + EXPECT_EQ(info->GetAppTypes().size(), 1); + EXPECT_EQ(info->GetAppTypes()[0], "dotnet"); + EXPECT_EQ(info->GetExtraArgs().size(), 7); + EXPECT_EQ(info->GetExtraArgs()[0], + "--PADDING_TO_CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE_PADDING_TO_" + "CHANGE_CMDLINE_PADDING_TO_CHANGE_CMDLINE"); + EXPECT_EQ(info->GetExtraArgs()[1], "--profile"); + EXPECT_EQ(info->GetExtraArgs()[2], "--appType"); + EXPECT_EQ(info->GetExtraArgs()[3], "dotnet"); + EXPECT_EQ(info->GetExtraArgs()[4], "TIZEN_UIFW"); + EXPECT_EQ(info->GetExtraArgs()[5], "ElmSharp"); + EXPECT_EQ(info->GetExtraArgs()[6], "--standalone"); +} + +TEST_F(LaunchpadTest, LoaderInfoTest) { +/* Test loader info file +[LOADER] +NAME hw-loader1 +EXE /usr/bin/launchpad-loader +APP_TYPE capp|c++app +HW_ACC ON +DETECTION_METHOD TIMEOUT|VISIBILITY +TIMEOUT 5000 +EXTRA loader_type hw-loader +EXTRA_ARRAY preload +EXTRA_ARRAY_VAL /usr/lib/libappcore-efl.so.1 +EXTRA_ARRAY_VAL /usr/lib/libappcore-common.so.1 +EXTRA_ARRAY_VAL /usr/lib/libcapi-appfw-application.so.0 +EXTRA_ARRAY_VAL /usr/lib/ecore_imf/modules/wayland/v-1.25/module.so +EXTRA_ARRAY_VAL /usr/lib/libdali-toolkit.so +EXTRA_ARRAY_VAL /usr/lib/libcairo.so.2 +EXTRA_ARRAY_VAL /usr/lib/libcapi-media-player.so.0 +EXTRA_ARRAY_VAL /usr/lib/libcapi-media-camera.so.0 +EXTRA_ARRAY_VAL /usr/lib/ecore_evas/engines/extn/v-1.25/module.so +ALTERNATIVE_LOADER common-loader1 +EXTRA threads 7 +*/ + + LoaderInfoInflator inflator; + auto list = inflator.Inflate("."); + EXPECT_EQ(list.size(), 1); + auto info = std::move(list.front()); + EXPECT_EQ(info->GetName(), "hw-loader1"); + EXPECT_EQ(info->GetExe(), "/usr/bin/launchpad-loader"); + EXPECT_EQ(info->GetAppTypes().size(), 2); + EXPECT_EQ(info->GetAppTypes()[0], "capp"); + EXPECT_EQ(info->GetAppTypes()[1], "c++app"); + EXPECT_EQ(info->GetHwAcc(), "ON"); + EXPECT_EQ(info->GetDetectionMethod(), LoaderMethod::Timeout | + LoaderMethod::Visibility | + LoaderMethod::Install); + EXPECT_EQ(info->GetTimeoutVal(), 5000); + auto& b = info->GetExtra(); + EXPECT_EQ(b.GetString("loader_type"), "hw-loader"); + EXPECT_EQ(b.GetString("threads"), "7"); + auto arr = b.GetStringArray("preload"); + EXPECT_EQ(arr.size(), 9); + EXPECT_EQ(arr[0], "/usr/lib/libappcore-efl.so.1"); + EXPECT_EQ(arr[1], "/usr/lib/libappcore-common.so.1"); + EXPECT_EQ(arr[2], "/usr/lib/libcapi-appfw-application.so.0"); + EXPECT_EQ(arr[3], "/usr/lib/ecore_imf/modules/wayland/v-1.25/module.so"); + EXPECT_EQ(arr[4], "/usr/lib/libdali-toolkit.so"); + EXPECT_EQ(arr[5], "/usr/lib/libcairo.so.2"); + EXPECT_EQ(arr[6], "/usr/lib/libcapi-media-player.so.0"); + EXPECT_EQ(arr[7], "/usr/lib/libcapi-media-camera.so.0"); + EXPECT_EQ(arr[8], "/usr/lib/ecore_evas/engines/extn/v-1.25/module.so"); +} diff --git a/tests/launchpad-process-pool-unittest/src/test_main.cc b/tests/launchpad-process-pool-unittest/src/test_main.cc new file mode 100644 index 0000000..3822224 --- /dev/null +++ b/tests/launchpad-process-pool-unittest/src/test_main.cc @@ -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. + */ + +#include +#include +#include + +#include + +extern "C" int __dlog_print(log_id_t log_id, int prio, const char* tag, + const char* fmt, ...) { + printf("%s:", tag); + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + return 0; +} + +int main(int argc, char** argv) { + try { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); + } catch (std::exception const &e) { + std::cout << "test_main caught exception: " << e.what() << std::endl; + return -1; + } +} -- 2.7.4 From c1440580ea9009b99556b94d1ea6664d5030a1d4 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Mon, 13 Feb 2023 11:11:24 +0900 Subject: [PATCH 13/16] Modify launchpad-process-pool directory structure launchpad-process-pool directory structure is modified as follow. launchpad-process-pool | *.cc | *.hh Change-Id: I30c244da4b5fe20db85ea7ad00209cb5bd8cc84c Signed-off-by: Changgyu Choi --- src/launchpad-process-pool/CMakeLists.txt | 6 +- .../{src => }/debugger_info.cc | 7 +- .../{inc => }/debugger_info.hh | 0 .../{src => }/launcher_info.cc | 7 +- .../{inc => }/launcher_info.hh | 0 src/launchpad-process-pool/{src => }/launchpad.cc | 36 +-- src/launchpad-process-pool/launchpad_config.cc | 303 +++++++++++++++++++ .../{inc => }/launchpad_config.h | 0 .../{src => }/launchpad_dbus.cc | 5 +- .../{inc => }/launchpad_dbus.h | 0 .../{src => }/launchpad_debug.cc | 11 +- .../{inc => }/launchpad_debug.h | 0 .../{src => }/launchpad_inotify.cc | 5 +- .../{inc => }/launchpad_inotify.h | 0 .../{src => }/launchpad_io_channel.cc | 5 +- .../{inc => }/launchpad_io_channel.h | 0 .../{src => }/launchpad_log.cc | 9 +- .../{inc => }/launchpad_log.h | 0 .../{src => }/launchpad_logger.cc | 7 +- .../{inc => }/launchpad_logger.h | 0 .../{src => }/launchpad_memory_monitor.cc | 9 +- .../{inc => }/launchpad_memory_monitor.h | 0 .../{src => }/launchpad_signal.cc | 15 +- .../{inc => }/launchpad_signal.h | 0 .../{src => }/launchpad_worker.cc | 5 +- .../{inc => }/launchpad_worker.h | 0 .../{src => }/loader_info.cc | 7 +- .../{inc => }/loader_info.hh | 2 +- src/launchpad-process-pool/{inc => }/slot_info.h | 0 src/launchpad-process-pool/src/launchpad_config.cc | 332 --------------------- src/launchpad-process-pool/{src => }/util.cc | 0 src/launchpad-process-pool/{inc => }/util.hh | 0 .../launchpad-process-pool-unittest/CMakeLists.txt | 8 +- .../src/test_launchpad.cc | 8 +- 34 files changed, 386 insertions(+), 401 deletions(-) rename src/launchpad-process-pool/{src => }/debugger_info.cc (97%) rename src/launchpad-process-pool/{inc => }/debugger_info.hh (100%) rename src/launchpad-process-pool/{src => }/launcher_info.cc (96%) rename src/launchpad-process-pool/{inc => }/launcher_info.hh (100%) rename src/launchpad-process-pool/{src => }/launchpad.cc (99%) create mode 100644 src/launchpad-process-pool/launchpad_config.cc rename src/launchpad-process-pool/{inc => }/launchpad_config.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_dbus.cc (98%) rename src/launchpad-process-pool/{inc => }/launchpad_dbus.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_debug.cc (97%) rename src/launchpad-process-pool/{inc => }/launchpad_debug.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_inotify.cc (97%) rename src/launchpad-process-pool/{inc => }/launchpad_inotify.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_io_channel.cc (97%) rename src/launchpad-process-pool/{inc => }/launchpad_io_channel.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_log.cc (89%) rename src/launchpad-process-pool/{inc => }/launchpad_log.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_logger.cc (97%) rename src/launchpad-process-pool/{inc => }/launchpad_logger.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_memory_monitor.cc (94%) rename src/launchpad-process-pool/{inc => }/launchpad_memory_monitor.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_signal.cc (96%) rename src/launchpad-process-pool/{inc => }/launchpad_signal.h (100%) rename src/launchpad-process-pool/{src => }/launchpad_worker.cc (97%) rename src/launchpad-process-pool/{inc => }/launchpad_worker.h (100%) rename src/launchpad-process-pool/{src => }/loader_info.cc (99%) rename src/launchpad-process-pool/{inc => }/loader_info.hh (99%) rename src/launchpad-process-pool/{inc => }/slot_info.h (100%) delete mode 100644 src/launchpad-process-pool/src/launchpad_config.cc rename src/launchpad-process-pool/{src => }/util.cc (100%) rename src/launchpad-process-pool/{inc => }/util.hh (100%) diff --git a/src/launchpad-process-pool/CMakeLists.txt b/src/launchpad-process-pool/CMakeLists.txt index 3175dac..e619fe3 100644 --- a/src/launchpad-process-pool/CMakeLists.txt +++ b/src/launchpad-process-pool/CMakeLists.txt @@ -1,8 +1,8 @@ -AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} LAUNCHPAD_PROCESS_POOL_SRCS) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../lib/common/src LIB_COMMON_SRCS) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/inc) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/..) ADD_EXECUTABLE(${TARGET_LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_SRCS} @@ -11,7 +11,7 @@ SET_TARGET_PROPERTIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PROPERTIES SKIP_BUILD_RPATH TRUE) TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/inc) + ${CMAKE_CURRENT_SOURCE_DIR}/..) TARGET_INCLUDE_DIRECTORIES(${TARGET_LAUNCHPAD_PROCESS_POOL} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../lib/common/inc) diff --git a/src/launchpad-process-pool/src/debugger_info.cc b/src/launchpad-process-pool/debugger_info.cc similarity index 97% rename from src/launchpad-process-pool/src/debugger_info.cc rename to src/launchpad-process-pool/debugger_info.cc index 8cbeaf7..5ae58bd 100644 --- a/src/launchpad-process-pool/src/debugger_info.cc +++ b/src/launchpad-process-pool/debugger_info.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/debugger_info.hh" + #include #include #include @@ -27,9 +29,8 @@ #include #include -#include "debugger_info.hh" -#include "launchpad_common.h" -#include "util.hh" +#include "launchpad-process-pool/util.hh" +#include "lib/common/inc/launchpad_common.h" namespace launchpad { namespace { diff --git a/src/launchpad-process-pool/inc/debugger_info.hh b/src/launchpad-process-pool/debugger_info.hh similarity index 100% rename from src/launchpad-process-pool/inc/debugger_info.hh rename to src/launchpad-process-pool/debugger_info.hh diff --git a/src/launchpad-process-pool/src/launcher_info.cc b/src/launchpad-process-pool/launcher_info.cc similarity index 96% rename from src/launchpad-process-pool/src/launcher_info.cc rename to src/launchpad-process-pool/launcher_info.cc index 7387323..a8baacd 100644 --- a/src/launchpad-process-pool/src/launcher_info.cc +++ b/src/launchpad-process-pool/launcher_info.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/launcher_info.hh" + #include #include #include @@ -27,9 +29,8 @@ #include #include -#include "launcher_info.hh" -#include "launchpad_common.h" -#include "util.hh" +#include "launchpad-process-pool/util.hh" +#include "lib/common/inc/launchpad_common.h" namespace launchpad { namespace { diff --git a/src/launchpad-process-pool/inc/launcher_info.hh b/src/launchpad-process-pool/launcher_info.hh similarity index 100% rename from src/launchpad-process-pool/inc/launcher_info.hh rename to src/launchpad-process-pool/launcher_info.hh diff --git a/src/launchpad-process-pool/src/launchpad.cc b/src/launchpad-process-pool/launchpad.cc similarity index 99% rename from src/launchpad-process-pool/src/launchpad.cc rename to src/launchpad-process-pool/launchpad.cc index a71168f..6fd6ef4 100644 --- a/src/launchpad-process-pool/src/launchpad.cc +++ b/src/launchpad-process-pool/launchpad.cc @@ -40,24 +40,24 @@ #include -#include "key.h" -#include "launcher_info.hh" -#include "launchpad_common.h" -#include "launchpad_config.h" -#include "launchpad_dbus.h" -#include "launchpad_debug.h" -#include "launchpad_inotify.h" -#include "launchpad_io_channel.h" -#include "launchpad_log.h" -#include "launchpad_memory_monitor.h" -#include "launchpad_plugin.h" -#include "launchpad_proc.h" -#include "launchpad_signal.h" -#include "launchpad_types.h" -#include "launchpad_worker.h" -#include "loader_info.hh" -#include "perf.h" -#include "slot_info.h" +#include "launchpad-process-pool/launcher_info.hh" +#include "launchpad-process-pool/launchpad_config.h" +#include "launchpad-process-pool/launchpad_dbus.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_log.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" +#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" #define AUL_PR_NAME 16 #define EXEC_CANDIDATE_EXPIRED 5 diff --git a/src/launchpad-process-pool/launchpad_config.cc b/src/launchpad-process-pool/launchpad_config.cc new file mode 100644 index 0000000..434973d --- /dev/null +++ b/src/launchpad-process-pool/launchpad_config.cc @@ -0,0 +1,303 @@ +/* + * 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/inc/launchpad_config.h b/src/launchpad-process-pool/launchpad_config.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_config.h rename to src/launchpad-process-pool/launchpad_config.h diff --git a/src/launchpad-process-pool/src/launchpad_dbus.cc b/src/launchpad-process-pool/launchpad_dbus.cc similarity index 98% rename from src/launchpad-process-pool/src/launchpad_dbus.cc rename to src/launchpad-process-pool/launchpad_dbus.cc index 7beff3d..231b8e4 100644 --- a/src/launchpad-process-pool/src/launchpad_dbus.cc +++ b/src/launchpad-process-pool/launchpad_dbus.cc @@ -14,13 +14,14 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_dbus.h" + #include #include #include #include -#include "launchpad_dbus.h" -#include "log_private.h" +#include "lib/common/inc/log_private.h" #define AUL_DBUS_PATH "/aul/dbus_handler" #define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" diff --git a/src/launchpad-process-pool/inc/launchpad_dbus.h b/src/launchpad-process-pool/launchpad_dbus.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_dbus.h rename to src/launchpad-process-pool/launchpad_dbus.h diff --git a/src/launchpad-process-pool/src/launchpad_debug.cc b/src/launchpad-process-pool/launchpad_debug.cc similarity index 97% rename from src/launchpad-process-pool/src/launchpad_debug.cc rename to src/launchpad-process-pool/launchpad_debug.cc index 12f8bdc..d94c194 100644 --- a/src/launchpad-process-pool/src/launchpad_debug.cc +++ b/src/launchpad-process-pool/launchpad_debug.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_debug.h" + #include #include #include @@ -27,11 +29,10 @@ #include -#include "debugger_info.hh" -#include "key.h" -#include "launchpad_common.h" -#include "launchpad_debug.h" -#include "launchpad_types.h" +#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" diff --git a/src/launchpad-process-pool/inc/launchpad_debug.h b/src/launchpad-process-pool/launchpad_debug.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_debug.h rename to src/launchpad-process-pool/launchpad_debug.h diff --git a/src/launchpad-process-pool/src/launchpad_inotify.cc b/src/launchpad-process-pool/launchpad_inotify.cc similarity index 97% rename from src/launchpad-process-pool/src/launchpad_inotify.cc rename to src/launchpad-process-pool/launchpad_inotify.cc index 2afc91a..82ffcdc 100644 --- a/src/launchpad-process-pool/src/launchpad_inotify.cc +++ b/src/launchpad-process-pool/launchpad_inotify.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_inotify.h" + #include #include #include @@ -21,8 +23,7 @@ #include #include -#include "launchpad_inotify.h" -#include "log_private.h" +#include "lib/common/inc/log_private.h" struct inotify_watch_info_s { int fd; diff --git a/src/launchpad-process-pool/inc/launchpad_inotify.h b/src/launchpad-process-pool/launchpad_inotify.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_inotify.h rename to src/launchpad-process-pool/launchpad_inotify.h diff --git a/src/launchpad-process-pool/src/launchpad_io_channel.cc b/src/launchpad-process-pool/launchpad_io_channel.cc similarity index 97% rename from src/launchpad-process-pool/src/launchpad_io_channel.cc rename to src/launchpad-process-pool/launchpad_io_channel.cc index 5987793..9fded4e 100644 --- a/src/launchpad-process-pool/src/launchpad_io_channel.cc +++ b/src/launchpad-process-pool/launchpad_io_channel.cc @@ -14,13 +14,14 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_io_channel.h" + #include #include #include #include -#include "launchpad_io_channel.h" -#include "log_private.h" +#include "lib/common/inc/log_private.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) diff --git a/src/launchpad-process-pool/inc/launchpad_io_channel.h b/src/launchpad-process-pool/launchpad_io_channel.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_io_channel.h rename to src/launchpad-process-pool/launchpad_io_channel.h diff --git a/src/launchpad-process-pool/src/launchpad_log.cc b/src/launchpad-process-pool/launchpad_log.cc similarity index 89% rename from src/launchpad-process-pool/src/launchpad_log.cc rename to src/launchpad-process-pool/launchpad_log.cc index 59128ab..21ade94 100644 --- a/src/launchpad-process-pool/src/launchpad_log.cc +++ b/src/launchpad-process-pool/launchpad_log.cc @@ -14,14 +14,15 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_logger.h" + #include #include #include -#include "launchpad_config.h" -#include "launchpad_log.h" -#include "launchpad_logger.h" -#include "log_private.h" +#include "launchpad-process-pool/launchpad_config.h" +#include "launchpad-process-pool/launchpad_log.h" +#include "lib/common/inc/log_private.h" #define LOG_FILE "launchpad.log" #define PATH_LAUNCHPAD_LOG "/var/log/appfw/launchpad/launchpad.log" diff --git a/src/launchpad-process-pool/inc/launchpad_log.h b/src/launchpad-process-pool/launchpad_log.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_log.h rename to src/launchpad-process-pool/launchpad_log.h diff --git a/src/launchpad-process-pool/src/launchpad_logger.cc b/src/launchpad-process-pool/launchpad_logger.cc similarity index 97% rename from src/launchpad-process-pool/src/launchpad_logger.cc rename to src/launchpad-process-pool/launchpad_logger.cc index 592d73e..0de93d1 100644 --- a/src/launchpad-process-pool/src/launchpad_logger.cc +++ b/src/launchpad-process-pool/launchpad_logger.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_logger.h" + #include #include #include @@ -28,9 +30,8 @@ #include #include -#include "launchpad_config.h" -#include "launchpad_logger.h" -#include "log_private.h" +#include "launchpad-process-pool/launchpad_config.h" +#include "lib/common/inc/log_private.h" #define LAUNCHPAD_LOG_APPFW_PATH "/var/log/appfw" #define LAUNCHPAD_LOG_PATH "/var/log/appfw/launchpad" diff --git a/src/launchpad-process-pool/inc/launchpad_logger.h b/src/launchpad-process-pool/launchpad_logger.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_logger.h rename to src/launchpad-process-pool/launchpad_logger.h diff --git a/src/launchpad-process-pool/src/launchpad_memory_monitor.cc b/src/launchpad-process-pool/launchpad_memory_monitor.cc similarity index 94% rename from src/launchpad-process-pool/src/launchpad_memory_monitor.cc rename to src/launchpad-process-pool/launchpad_memory_monitor.cc index d2b60ca..c69fe73 100644 --- a/src/launchpad-process-pool/src/launchpad_memory_monitor.cc +++ b/src/launchpad-process-pool/launchpad_memory_monitor.cc @@ -14,16 +14,17 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_memory_monitor.h" + #include #include #include #include #include -#include "launchpad_config.h" -#include "launchpad_memory_monitor.h" -#include "launchpad_proc.h" -#include "log_private.h" +#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 diff --git a/src/launchpad-process-pool/inc/launchpad_memory_monitor.h b/src/launchpad-process-pool/launchpad_memory_monitor.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_memory_monitor.h rename to src/launchpad-process-pool/launchpad_memory_monitor.h diff --git a/src/launchpad-process-pool/src/launchpad_signal.cc b/src/launchpad-process-pool/launchpad_signal.cc similarity index 96% rename from src/launchpad-process-pool/src/launchpad_signal.cc rename to src/launchpad-process-pool/launchpad_signal.cc index ca305b0..be233a0 100644 --- a/src/launchpad-process-pool/src/launchpad_signal.cc +++ b/src/launchpad-process-pool/launchpad_signal.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_signal.h" + #include #include #include @@ -24,13 +26,12 @@ #include #include -#include "launchpad_common.h" -#include "launchpad_dbus.h" -#include "launchpad_io_channel.h" -#include "launchpad_proc.h" -#include "launchpad_signal.h" -#include "launchpad_socket.h" -#include "log_private.h" +#include "launchpad-process-pool/launchpad_dbus.h" +#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" #define HYDRA_SIGCHLD_SOCK ".hydra-sigchld-sock" diff --git a/src/launchpad-process-pool/inc/launchpad_signal.h b/src/launchpad-process-pool/launchpad_signal.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_signal.h rename to src/launchpad-process-pool/launchpad_signal.h diff --git a/src/launchpad-process-pool/src/launchpad_worker.cc b/src/launchpad-process-pool/launchpad_worker.cc similarity index 97% rename from src/launchpad-process-pool/src/launchpad_worker.cc rename to src/launchpad-process-pool/launchpad_worker.cc index 15b53a5..4729e48 100644 --- a/src/launchpad-process-pool/src/launchpad_worker.cc +++ b/src/launchpad-process-pool/launchpad_worker.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/launchpad_worker.h" + #include #include #include @@ -25,8 +27,7 @@ #include #include -#include "launchpad_worker.h" -#include "log_private.h" +#include "lib/common/inc/log_private.h" struct job_s { worker_job_cb callback; diff --git a/src/launchpad-process-pool/inc/launchpad_worker.h b/src/launchpad-process-pool/launchpad_worker.h similarity index 100% rename from src/launchpad-process-pool/inc/launchpad_worker.h rename to src/launchpad-process-pool/launchpad_worker.h diff --git a/src/launchpad-process-pool/src/loader_info.cc b/src/launchpad-process-pool/loader_info.cc similarity index 99% rename from src/launchpad-process-pool/src/loader_info.cc rename to src/launchpad-process-pool/loader_info.cc index 548dfe1..28e2934 100644 --- a/src/launchpad-process-pool/src/loader_info.cc +++ b/src/launchpad-process-pool/loader_info.cc @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "launchpad-process-pool/loader_info.hh" + #include #include #include @@ -25,9 +27,8 @@ #include #include -#include "launchpad_common.h" -#include "loader_info.hh" -#include "util.hh" +#include "launchpad-process-pool/util.hh" +#include "lib/common/inc/launchpad_common.h" namespace launchpad { namespace { diff --git a/src/launchpad-process-pool/inc/loader_info.hh b/src/launchpad-process-pool/loader_info.hh similarity index 99% rename from src/launchpad-process-pool/inc/loader_info.hh rename to src/launchpad-process-pool/loader_info.hh index d96e029..105aecb 100644 --- a/src/launchpad-process-pool/inc/loader_info.hh +++ b/src/launchpad-process-pool/loader_info.hh @@ -25,7 +25,7 @@ #include #include -#include "util.hh" +#include "launchpad-process-pool/util.hh" namespace launchpad { diff --git a/src/launchpad-process-pool/inc/slot_info.h b/src/launchpad-process-pool/slot_info.h similarity index 100% rename from src/launchpad-process-pool/inc/slot_info.h rename to src/launchpad-process-pool/slot_info.h diff --git a/src/launchpad-process-pool/src/launchpad_config.cc b/src/launchpad-process-pool/src/launchpad_config.cc deleted file mode 100644 index 33a448f..0000000 --- a/src/launchpad-process-pool/src/launchpad_config.cc +++ /dev/null @@ -1,332 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "launchpad_common.h" -#include "launchpad_config.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/src/util.cc b/src/launchpad-process-pool/util.cc similarity index 100% rename from src/launchpad-process-pool/src/util.cc rename to src/launchpad-process-pool/util.cc diff --git a/src/launchpad-process-pool/inc/util.hh b/src/launchpad-process-pool/util.hh similarity index 100% rename from src/launchpad-process-pool/inc/util.hh rename to src/launchpad-process-pool/util.hh diff --git a/tests/launchpad-process-pool-unittest/CMakeLists.txt b/tests/launchpad-process-pool-unittest/CMakeLists.txt index c79c682..0fee590 100644 --- a/tests/launchpad-process-pool-unittest/CMakeLists.txt +++ b/tests/launchpad-process-pool-unittest/CMakeLists.txt @@ -5,20 +5,20 @@ INCLUDE(FindPkgConfig) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -Wall -Winline") -SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++17 -DUNIT_TEST") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS} -std=c++17") SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") SET(CMAKE_CXX_FLAGS_RELEASE "-O2") INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/common/inc) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/inc) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../../src/) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src UNITTESTS_SOURCES) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/lib/common/src LAUNCHPAD_COMMON_SOURCES) -AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/src LAUNCHPAD_PROCESS_POOL_SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool LAUNCHPAD_PROCESS_POOL_SOURCES) LIST(REMOVE_ITEM LAUNCHPAD_PROCESS_POOL_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/src/launchpad.cc" + "${CMAKE_CURRENT_SOURCE_DIR}/../../src/launchpad-process-pool/launchpad.cc" ) ADD_EXECUTABLE(${PROJECT_NAME} diff --git a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc index ad9e83e..5f604bb 100644 --- a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc +++ b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc @@ -23,15 +23,17 @@ #include #include -#include "debugger_info.hh" -#include "launcher_info.hh" -#include "loader_info.hh" +#include "launchpad-process-pool/debugger_info.hh" +#include "launchpad-process-pool/launcher_info.hh" +#include "launchpad-process-pool/loader_info.hh" using ::testing::AtLeast; using namespace launchpad; class LaunchpadTest : public ::testing::Test { public: + LaunchpadTest() = default; + virtual void SetUp() { std::ofstream of; of.open(test_debugger); -- 2.7.4 From df945d328f8e3fd2c90a6a023c606bf6ff49a122 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Thu, 16 Feb 2023 14:04:33 +0900 Subject: [PATCH 14/16] Fix library path for aarch64 Change-Id: I8aa04dccb3d66aadccd31f6571fbab1ad048736e Signed-off-by: Changgyu Choi --- src/lib/launchpad-hydra/src/launchpad_hydra.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/launchpad-hydra/src/launchpad_hydra.c b/src/lib/launchpad-hydra/src/launchpad_hydra.c index ba385db..e4a2eda 100644 --- a/src/lib/launchpad-hydra/src/launchpad_hydra.c +++ b/src/lib/launchpad-hydra/src/launchpad_hydra.c @@ -100,7 +100,7 @@ static void __fini_signal(void) static int (*__security_manager_prepare_app_candidate)(void); static int __load_security_manager_func(void) { -#define PATH_SECURITY_MANAGER_CLIENT "/usr/lib/libsecurity-manager-client.so.3" +#define PATH_SECURITY_MANAGER_CLIENT LIBDIR"/libsecurity-manager-client.so.3" void *handle; handle = dlopen(PATH_SECURITY_MANAGER_CLIENT, RTLD_LAZY | RTLD_LOCAL); -- 2.7.4 From 100678dd3dd282881f51f4407701edad5b1f157e Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Thu, 16 Feb 2023 14:04:33 +0900 Subject: [PATCH 15/16] Rename sample loader lib path args to /test Change-Id: I8aa04dccb3d66aadccd31f6571fbab1ad048736e Signed-off-by: Changgyu Choi --- .../src/test_launchpad.cc | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc index 5f604bb..0133f12 100644 --- a/tests/launchpad-process-pool-unittest/src/test_launchpad.cc +++ b/tests/launchpad-process-pool-unittest/src/test_launchpad.cc @@ -89,15 +89,15 @@ DETECTION_METHOD TIMEOUT|VISIBILITY TIMEOUT 5000 EXTRA loader_type hw-loader EXTRA_ARRAY preload -EXTRA_ARRAY_VAL /usr/lib/libappcore-efl.so.1 -EXTRA_ARRAY_VAL /usr/lib/libappcore-common.so.1 -EXTRA_ARRAY_VAL /usr/lib/libcapi-appfw-application.so.0 -EXTRA_ARRAY_VAL /usr/lib/ecore_imf/modules/wayland/v-1.25/module.so -EXTRA_ARRAY_VAL /usr/lib/libdali-toolkit.so -EXTRA_ARRAY_VAL /usr/lib/libcairo.so.2 -EXTRA_ARRAY_VAL /usr/lib/libcapi-media-player.so.0 -EXTRA_ARRAY_VAL /usr/lib/libcapi-media-camera.so.0 -EXTRA_ARRAY_VAL /usr/lib/ecore_evas/engines/extn/v-1.25/module.so +EXTRA_ARRAY_VAL /test/libappcore-efl.so.1 +EXTRA_ARRAY_VAL /test/libappcore-common.so.1 +EXTRA_ARRAY_VAL /test/libcapi-appfw-application.so.0 +EXTRA_ARRAY_VAL /test/ecore_imf/modules/wayland/v-1.25/module.so +EXTRA_ARRAY_VAL /test/libdali-toolkit.so +EXTRA_ARRAY_VAL /test/libcairo.so.2 +EXTRA_ARRAY_VAL /test/libcapi-media-player.so.0 +EXTRA_ARRAY_VAL /test/libcapi-media-camera.so.0 +EXTRA_ARRAY_VAL /test/ecore_evas/engines/extn/v-1.25/module.so ALTERNATIVE_LOADER common-loader1 EXTRA threads 7 @@ -194,15 +194,15 @@ DETECTION_METHOD TIMEOUT|VISIBILITY TIMEOUT 5000 EXTRA loader_type hw-loader EXTRA_ARRAY preload -EXTRA_ARRAY_VAL /usr/lib/libappcore-efl.so.1 -EXTRA_ARRAY_VAL /usr/lib/libappcore-common.so.1 -EXTRA_ARRAY_VAL /usr/lib/libcapi-appfw-application.so.0 -EXTRA_ARRAY_VAL /usr/lib/ecore_imf/modules/wayland/v-1.25/module.so -EXTRA_ARRAY_VAL /usr/lib/libdali-toolkit.so -EXTRA_ARRAY_VAL /usr/lib/libcairo.so.2 -EXTRA_ARRAY_VAL /usr/lib/libcapi-media-player.so.0 -EXTRA_ARRAY_VAL /usr/lib/libcapi-media-camera.so.0 -EXTRA_ARRAY_VAL /usr/lib/ecore_evas/engines/extn/v-1.25/module.so +EXTRA_ARRAY_VAL /test/libappcore-efl.so.1 +EXTRA_ARRAY_VAL /test/libappcore-common.so.1 +EXTRA_ARRAY_VAL /test/libcapi-appfw-application.so.0 +EXTRA_ARRAY_VAL /test/ecore_imf/modules/wayland/v-1.25/module.so +EXTRA_ARRAY_VAL /test/libdali-toolkit.so +EXTRA_ARRAY_VAL /test/libcairo.so.2 +EXTRA_ARRAY_VAL /test/libcapi-media-player.so.0 +EXTRA_ARRAY_VAL /test/libcapi-media-camera.so.0 +EXTRA_ARRAY_VAL /test/ecore_evas/engines/extn/v-1.25/module.so ALTERNATIVE_LOADER common-loader1 EXTRA threads 7 */ @@ -226,13 +226,13 @@ EXTRA threads 7 EXPECT_EQ(b.GetString("threads"), "7"); auto arr = b.GetStringArray("preload"); EXPECT_EQ(arr.size(), 9); - EXPECT_EQ(arr[0], "/usr/lib/libappcore-efl.so.1"); - EXPECT_EQ(arr[1], "/usr/lib/libappcore-common.so.1"); - EXPECT_EQ(arr[2], "/usr/lib/libcapi-appfw-application.so.0"); - EXPECT_EQ(arr[3], "/usr/lib/ecore_imf/modules/wayland/v-1.25/module.so"); - EXPECT_EQ(arr[4], "/usr/lib/libdali-toolkit.so"); - EXPECT_EQ(arr[5], "/usr/lib/libcairo.so.2"); - EXPECT_EQ(arr[6], "/usr/lib/libcapi-media-player.so.0"); - EXPECT_EQ(arr[7], "/usr/lib/libcapi-media-camera.so.0"); - EXPECT_EQ(arr[8], "/usr/lib/ecore_evas/engines/extn/v-1.25/module.so"); + EXPECT_EQ(arr[0], "/test/libappcore-efl.so.1"); + EXPECT_EQ(arr[1], "/test/libappcore-common.so.1"); + EXPECT_EQ(arr[2], "/test/libcapi-appfw-application.so.0"); + EXPECT_EQ(arr[3], "/test/ecore_imf/modules/wayland/v-1.25/module.so"); + EXPECT_EQ(arr[4], "/test/libdali-toolkit.so"); + EXPECT_EQ(arr[5], "/test/libcairo.so.2"); + EXPECT_EQ(arr[6], "/test/libcapi-media-player.so.0"); + EXPECT_EQ(arr[7], "/test/libcapi-media-camera.so.0"); + EXPECT_EQ(arr[8], "/test/ecore_evas/engines/extn/v-1.25/module.so"); } -- 2.7.4 From 86016df1eb169520491f11cc17d492798b03f0e1 Mon Sep 17 00:00:00 2001 From: Changgyu Choi Date: Thu, 16 Feb 2023 14:20:16 +0900 Subject: [PATCH 16/16] Release version 0.24.0 Changes: - Refactor launchpad to c++ - Add unittest - Modify launchpad-process-pool directory structure - Fix library path for aarch64 - Rename sample loader lib path args to /test Change-Id: I846cd507e348b330bea0ae5d3eb44d2cfc231f49 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 413133e..bee045b 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.23.2 +Version: 0.24.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4