From aea787b684bc5fdc3fa1fb1b64bc95d5211866cf Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 20 Feb 2020 09:32:19 +0900 Subject: [PATCH 01/16] Fix log format Change-Id: I7105f7057dc81bb6d40b3bfd5c7ad62f14a57058 Signed-off-by: Hwankyu Jhun --- src/parser/launchpad_parser_plugin.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parser/launchpad_parser_plugin.cc b/src/parser/launchpad_parser_plugin.cc index a880a6e..95deccb 100644 --- a/src/parser/launchpad_parser_plugin.cc +++ b/src/parser/launchpad_parser_plugin.cc @@ -36,7 +36,7 @@ int LaunchpadParser::WriteToFile(string pkgid) { if (access(LOADERS_DIRECTORY_PATH, F_OK) != 0) mkdir(LOADERS_DIRECTORY_PATH, 0644); - LOGI("write to file (%d)", loader_list_.size()); + LOGI("write to file (%zu)", loader_list_.size()); for (auto& i : loader_list_) { std::ofstream out_file; LOGI("write ID (%s)", i->GetId().c_str()); -- 2.7.4 From c8420009b043419336926914312b675e925646be Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 20 Feb 2020 09:32:33 +0900 Subject: [PATCH 02/16] Release version 0.12.1 Changes: - Fix log format Change-Id: I7fdd6ddf39a2b876d53312ba8e4e5ef26b4c6a59 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 3cd3478..db73636 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.12.0 +Version: 0.12.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 1c9a87dca5fb04388284b35f41106dd7111d9e29 Mon Sep 17 00:00:00 2001 From: hyunho Date: Thu, 20 Feb 2020 11:11:36 +0900 Subject: [PATCH 03/16] Add app_defined_loader Change-Id: I9ec6d2202ec3e6596a19b787a204703771996669 Signed-off-by: hyunho --- packaging/app-defined-loader.manifest | 8 + packaging/launchpad.spec | 14 + src/CMakeLists.txt | 2 + src/app_defined_loader/CMakeLists.txt | 69 +++++ src/app_defined_loader/src/app_defined_loader.cc | 330 +++++++++++++++++++++++ src/common/inc/launchpad_common.h | 14 + src/launchpad/src/launchpad.c | 12 +- src/loader/src/launchpad_loader.c | 5 - 8 files changed, 440 insertions(+), 14 deletions(-) create mode 100644 packaging/app-defined-loader.manifest create mode 100644 src/app_defined_loader/CMakeLists.txt create mode 100644 src/app_defined_loader/src/app_defined_loader.cc diff --git a/packaging/app-defined-loader.manifest b/packaging/app-defined-loader.manifest new file mode 100644 index 0000000..bd30b8b --- /dev/null +++ b/packaging/app-defined-loader.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index db73636..5935833 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -10,6 +10,7 @@ Source102: launchpad-process-pool.socket Source1001: %{name}.manifest Source1002: lib%{name}.manifest Source1003: %{name}-loader.manifest +Source1004: app-defined-loader.manifest BuildRequires: cmake BuildRequires: pkgconfig(bundle) @@ -72,6 +73,13 @@ Group: Application Framework/Application Launcher %description -n launchpad-loader Launchpad-Loader for launching applications +%package -n app-defined-loader +Summary: App-Defined-Loader for launching applications +Group: Application Framework/Application Launcher + +%description -n app-defined-loader +App-Defined-Loader for launching applications + %package -n liblaunchpad Summary: Launchpad library Group: Development/Libraries @@ -92,6 +100,7 @@ Launchpad library (devel) cp %{SOURCE1001} . cp %{SOURCE1002} . cp %{SOURCE1003} . +cp %{SOURCE1004} . %build %if 0%{?sec_build_binary_debug_enable} @@ -160,6 +169,11 @@ ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.targ %{_prefix}/share/aul/default.loader %{_bindir}/launchpad-loader +%files -n app-defined-loader +%manifest app-defined-loader.manifest +%license LICENSE +%{_bindir}/app-defined-loader + %files -n liblaunchpad %manifest liblaunchpad.manifest %license LICENSE diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3a0a104..dbab7f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) ADD_SUBDIRECTORY(launchpad) ADD_SUBDIRECTORY(lib) ADD_SUBDIRECTORY(loader) +ADD_SUBDIRECTORY(app_defined_loader) ADD_SUBDIRECTORY(hydra) ADD_SUBDIRECTORY(parser) ADD_DEPENDENCIES(launchpad-loader launchpad-lib) +ADD_DEPENDENCIES(app-defined-loader launchpad-lib) diff --git a/src/app_defined_loader/CMakeLists.txt b/src/app_defined_loader/CMakeLists.txt new file mode 100644 index 0000000..b0f869e --- /dev/null +++ b/src/app_defined_loader/CMakeLists.txt @@ -0,0 +1,69 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(app-defined-loader) +SET(APP_DEFINED_LOADER "app-defined-loader") + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(APP_DEFINED_LOADER_PKGS REQUIRED + dlog + ecore + ecore-core + bundle + aul + gio-2.0 + dbus-1 + libsystemd + ) + +FOREACH(flag ${APP_DEFINED_LOADER_PKGS_CFLAGS}) + SET(EXTRA_CFLAGS_loader "${EXTRA_CFLAGS_loader} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -Wl,-zdefs" ) +SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -fvisibility=hidden") +SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -fdata-sections -ffunction-sections -Wl,--gc-sections") +SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -D_FILE_OFFSET_BITS=64") +SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -Werror") + +IF(_TIZEN_FEATURE_PRELINK) +MESSAGE(STATUS "[__PRELINK__] Enable") +SET(EXTRA_CFLAGS_loader "${EXTRA_CFLAGS_loader} ${EXTRA_CFLAGS_common}") +ELSE(_TIZEN_FEATURE_PRELINK) +MESSAGE(STATUS "[__PRELINK__] Disable") +SET(EXTRA_CFLAGS_loader "${EXTRA_CFLAGS_loader} ${EXTRA_CFLAGS_common} -fPIE") +ENDIF(_TIZEN_FEATURE_PRELINK) + +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CFLAGS}") +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/common/inc) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/lib/inc) + +AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCES) +AUX_SOURCE_DIRECTORY(${CMAKE_SOURCE_DIR}/src/common/src COMMON_SOURCES) + +SET(APP_DEFINED_LOADER_SOURCE_FILES + ${COMMON_SOURCES} + ${SOURCES}) +ADD_EXECUTABLE(${APP_DEFINED_LOADER} ${APP_DEFINED_LOADER_SOURCE_FILES}) + +# To support 2.x applications which use their own shared libraries. +# Since we cannot set LD_LIBRARY_PATH directly by security issue, we make the +# dynamic linker looks in the CWD forcely. +TARGET_LINK_LIBRARIES(${APP_DEFINED_LOADER} "-ldl -Wl,-rpath,: -Wl,--disable-new-dtags") + +IF(_TIZEN_FEATURE_PRELINK) +TARGET_LINK_LIBRARIES(${APP_DEFINED_LOADER} ${APP_DEFINED_LOADER_PKGS_LDFLAGS} launchpad) +ELSE(_TIZEN_FEATURE_PRELINK) +TARGET_LINK_LIBRARIES(${APP_DEFINED_LOADER} ${APP_DEFINED_LOADER_PKGS_LDFLAGS} launchpad "-pie") +ENDIF(_TIZEN_FEATURE_PRELINK) + +SET_TARGET_PROPERTIES(${APP_DEFINED_LOADER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_loader}) +SET_TARGET_PROPERTIES(${APP_DEFINED_LOADER} + PROPERTIES SKIP_BUILD_RPATH TRUE + ) # remove rpath option that is automatically generated by cmake. +INSTALL(TARGETS ${APP_DEFINED_LOADER} DESTINATION bin) \ No newline at end of file diff --git a/src/app_defined_loader/src/app_defined_loader.cc b/src/app_defined_loader/src/app_defined_loader.cc new file mode 100644 index 0000000..39ba7d1 --- /dev/null +++ b/src/app_defined_loader/src/app_defined_loader.cc @@ -0,0 +1,330 @@ +/* + * 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 "launchpad_common.h" +#include "launchpad_types.h" +#include "launchpad.h" +#include "key.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "APP_DEFINED_LOADER" + +#ifndef PR_TASK_PERF_USER_TRACE +#define PR_TASK_PERF_USER_TRACE 666 +#endif + +#ifndef C_EXPORT +#define C_EXPORT extern "C" __attribute__((visibility("default"))) +#endif + +using namespace tizen_base; +using namespace std; +namespace launchpad { + +class AppDefinedLoader { + public: + AppDefinedLoader(int argc, char** argv) + : argc_(argc), argv_(argv) { + lifecycle_cb_ = shared_ptr(new loader_lifecycle_callback_s()); + lifecycle_cb_->create = OnCreate; + lifecycle_cb_->launch = OnLaunch; + lifecycle_cb_->terminate = OnTerminate; + + adapter_ = shared_ptr(new loader_adapter_s()); + adapter_->loop_begin = OnLoopBegin; + adapter_->loop_quit = OnLoopQuit; + adapter_->add_fd = OnAddFd; + adapter_->remove_fd = OnRemoveFd; + } + + ~AppDefinedLoader() { + _W("app defined loader destroyed"); + } + + shared_ptr GetLifeCycle() { + return lifecycle_cb_; + } + + shared_ptr GetAdapter() { + return adapter_; + } + + void SetLoaderPriority(bool enable) { + loader_priority_enabled_ = enable; + } + + void SetPriorityChanged(bool enable) { + priority_change_enabled_ = enable; + } + + bool IsLoaderPriorityEnabled() { + return loader_priority_enabled_; + } + + bool IsPriorityChangeEnabled() { + return priority_change_enabled_; + } + + void SetFdHandler(Ecore_Fd_Handler* fd_handler) { + fd_handler_ = fd_handler; + } + + Ecore_Fd_Handler* GetFdHandler() { + return fd_handler_; + } + + void SetReceiver(loader_receiver_cb receiver) { + receiver_cb_ = receiver; + } + + loader_receiver_cb GetReceiver() { + return receiver_cb_; + } + + private: + static void PreloadLib(Bundle data) { + vector so_array = data.GetStringArray("preload"); + if (so_array.size() == 0) + return; + for (auto& i : so_array) { + if (i.empty()) + continue; + void* handle = dlopen(i.c_str(), RTLD_NOW | RTLD_NODELETE); + if (handle == nullptr) + _E("fail to load : %s, err : %s", i.c_str(), dlerror()); + else + _D("preload %s# - handle : %p", i.c_str(), handle); + } + } + + static void OnCreate(bundle *extra, int type, void *user_data) { + _I("on create"); + AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + Bundle ex = Bundle(extra, false, false); + string loader_type = ex.GetString(KEY_LOADER_TYPE); + if (loader_type.empty()) { + _E("No loader type"); + return; + } + + if (loader->IsLoaderPriorityEnabled()) + launchpad_loader_set_priority(19); + loader->PreloadLib(ex); + ecore_init(); + setenv("AUL_LOADER_INIT", "1", 1); + + if (loader_type == LOADER_TYPE_SW) + setenv("AUL_HWACC", "none", 1); + else if (loader_type == LOADER_TYPE_HW) + setenv("AUL_HWACC", "hw", 1); + } + + 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 = (AppDefinedLoader*)user_data; + if (!loader->IsPriorityChangeEnabled()) + return 0; + + bundle *kb = launchpad_loader_get_bundle(); + if (kb == nullptr) + return 0; + + Bundle data(kb, false, false); + string high_priority = data.GetString(AUL_K_HIGHPRIORITY); + if (high_priority == "true") + launchpad_loader_set_priority(-12); + data.Delete(AUL_K_HIGHPRIORITY); + return 0; + } + + void DoExec(string libdir) { + _I("do exec"); + char err_str[MAX_LOCAL_BUFSZ]; + if (access(argv_[LOADER_ARG_PATH], F_OK | R_OK)) { + SECURE_LOGE("access() failed for file: \"%s\", error: %d (%s)", argv_[LOADER_ARG_PATH], errno, + strerror_r(errno, err_str, sizeof(err_str))); + } else { + SECURE_LOGD("[candidate] Exec application (%s)", + argv_[LOADER_ARG_PATH]); + _close_all_fds(); + if (!libdir.empty()) + setenv("LD_LIBRARY_PATH", libdir.c_str(), 1); + unsetenv("AUL_LOADER_INIT"); + unsetenv("AUL_HWACC"); + if (execv(argv_[LOADER_ARG_PATH], argv_) < 0) { + _send_message_to_logger(argv_[LOADER_ARG_PATH], + "Failed to execute a file. error(%d:%s)", errno, + strerror_r(errno, err_str, sizeof(err_str))); + } + } + } + + int DoDlOpen(bool restore, string old_cwd, string libdir) { + _I("do dlopen"); + string hwc_message = "" + to_string(getpid()) + "|lib loading start"; + prctl(PR_TASK_PERF_USER_TRACE, hwc_message.c_str(), hwc_message.size()); + void* handle = dlopen(argv_[LOADER_ARG_PATH], + RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE); + if (handle == nullptr) { + _E("dlopen(%s) is failed. error(%s)", argv_[LOADER_ARG_PATH], dlerror()); + DoExec(libdir); + return -1; + } + + hwc_message = "" + to_string(getpid()) + "|lib loading end"; + prctl(PR_TASK_PERF_USER_TRACE, hwc_message.c_str(), hwc_message.size()); + + if (restore && chdir(old_cwd.c_str())) + _E("failed to chdir: %d", errno); + + void* dl_main = dlsym(handle, "main"); + if (dl_main == nullptr) { + _E("dlsym not founded(%s). Please export 'main' function", dlerror()); + dlclose(handle); + DoExec(libdir); + return -1; + } + + _I("call main"); + return ((int (*)(int, char**))dl_main)(argc_, argv_); + } + + static int OnTerminate(int argc, char **argv, void *user_data) { + SECURE_LOGD("[candidate] Launch real application (%s)", argv[LOADER_ARG_PATH]); + char old_cwd[PATH_MAX] = {0, }; + AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + if (getcwd(old_cwd, sizeof(old_cwd)) == nullptr) { + loader->DoDlOpen(false, old_cwd, ""); + } else { + char* libdir = _get_libdir(argv[LOADER_ARG_PATH]); + if (libdir == NULL) { + return loader->DoDlOpen(false, old_cwd, ""); + } else { + /* To support 2.x applications which use their own shared libraries. + * We set '-rpath' to make the dynamic linker looks in the CWD forcely, + * so here we change working directory to find shared libraries well. + */ + bool restore = false; + if (chdir(libdir)) + _E("failed to chdir: %d", errno); + else + restore = true; + string libdir_str = string(libdir); + free(libdir); + return loader->DoDlOpen(restore, old_cwd, libdir_str); + } + } + return -1; + } + + static void OnLoopBegin(void* user_data) { + _I("on loop begin"); + ecore_main_loop_begin(); + } + + static void OnLoopQuit(void* user_data) { + _I("on loop quit"); + ecore_main_loop_quit(); + } + + static void OnAddFd(void* user_data, int fd, + loader_receiver_cb receiver) { + AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd, + (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR), + FdHandler, loader, nullptr, nullptr); + if (handler == nullptr) { + _E("fd_handler is NULL"); + close(fd); + exit(-1); + } + _I("set handler done (%d)", fd); + loader->SetFdHandler(handler); + loader->SetReceiver(receiver); + } + + static Eina_Bool FdHandler(void *user_data, Ecore_Fd_Handler *handler) { + _I("fd handler"); + AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + int fd = ecore_main_fd_handler_fd_get(handler); + if (fd == -1) { + _E("[candidate] ECORE_FD_GET"); + exit(-1); + } + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) { + if (loader->GetReceiver()) + loader->GetReceiver()(fd); + } else if (ecore_main_fd_handler_active_get( + handler, ECORE_FD_ERROR)) { + _E("[candidate] ECORE_FD_ERROR"); + close(fd); + exit(-1); + } + return ECORE_CALLBACK_CANCEL; + } + + static void OnRemoveFd(void *user_data, int fd) { + _I("remove fd"); + AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + if (loader->GetFdHandler() == nullptr) + return; + ecore_main_fd_handler_del(loader->GetFdHandler()); + loader->SetFdHandler(nullptr); + loader->SetReceiver(nullptr); + } + + private: + shared_ptr lifecycle_cb_ = nullptr; + shared_ptr adapter_ = nullptr; + bool loader_priority_enabled_ = false; + bool priority_change_enabled_ = false; + loader_receiver_cb receiver_cb_; + Ecore_Fd_Handler* fd_handler_ = nullptr; + int argc_; + char** argv_; +}; + +} + +C_EXPORT int main(int argc, char **argv) +{ + launchpad::AppDefinedLoader loader(argc, argv); + +#ifdef TIZEN_FEATURE_LOADER_PRIORITY + loader->SetLoaderPriority(true); +#endif +#ifdef TIZEN_FEATURE_PRIORITY_CHANGE + loader->SetPriorityChanged(true); +#endif + + return launchpad_loader_main(argc, argv, + loader.GetLifeCycle().get(), loader.GetAdapter().get(), &loader); +} \ No newline at end of file diff --git a/src/common/inc/launchpad_common.h b/src/common/inc/launchpad_common.h index dc60559..5d97b77 100644 --- a/src/common/inc/launchpad_common.h +++ b/src/common/inc/launchpad_common.h @@ -17,7 +17,9 @@ #ifndef __LAUNCHPAD_COMMON_H__ #define __LAUNCHPAD_COMMON_H__ +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif #include #include @@ -57,6 +59,11 @@ #define PAD_LOADER_ID_DIRECT 1 #define PAD_LOADER_ID_DYNAMIC_BASE 10 +#define KEY_LOADER_TYPE "loader_type" +#define LOADER_TYPE_COMMON "common-loader" +#define LOADER_TYPE_HW "hw-loader" +#define LOADER_TYPE_SW "sw-loader" + #define _E(fmt, arg...) LOGE(fmt, ##arg) #define _D(fmt, arg...) LOGD(fmt, ##arg) #define _W(fmt, arg...) LOGW(fmt, ##arg) @@ -72,6 +79,10 @@ #define ARRAY_SIZE(x) ((sizeof(x)) / sizeof(x[0])) #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) +#ifdef __cplusplus +extern "C" { +#endif + typedef struct _app_pkt_t { int cmd; int len; @@ -125,5 +136,8 @@ int _verify_proc_caps(void); int _prepare_id_file(void); void _print_hwc_log(const char *format, ...); +#ifdef __cplusplus +} +#endif #endif /* __LAUNCHPAD_COMMON_H__ */ diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 6d7b43b..f1a7d09 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -1600,7 +1600,6 @@ static int __dispatch_cmd_add_loader(bundle *kb) static int __dispatch_cmd_add_app_defined_loader(bundle *kb) { const char *loader_name; - const char *loader_path; int lid, len; candidate_process_context_t *cpc; const loader_info_t *info; @@ -1614,15 +1613,10 @@ static int __dispatch_cmd_add_app_defined_loader(bundle *kb) return -EINVAL; } - /* TODO: use app-defined-loader */ - loader_path = _loader_info_find_loader_path_by_loader_name( - loader_info_list, COMMON_LOADER_NAME); - info = _loader_info_find_loader_by_loader_name( app_defined_loader_info_list, loader_name); - if (loader_path == NULL || info == NULL || info->extra == NULL) { - _E("loader_name %s, loader_path %d, info %d", - loader_name, loader_path != NULL, info != NULL); + if (info == NULL || info->extra == NULL) { + _E("loader_name %s, info %d", loader_name, info != NULL); return -EINVAL; } @@ -1630,7 +1624,7 @@ static int __dispatch_cmd_add_app_defined_loader(bundle *kb) lid = __make_loader_id(); cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0, - loader_path, (const char *)extra, + "/usr/bin/app-defined-loader", (const char *)extra, METHOD_TIMEOUT | METHOD_VISIBILITY, METHOD_REQUEST | METHOD_AVAILABLE_MEMORY, METHOD_TTL | METHOD_OUT_OF_MEMORY, diff --git a/src/loader/src/launchpad_loader.c b/src/loader/src/launchpad_loader.c index 4dc371e..fee50e6 100644 --- a/src/loader/src/launchpad_loader.c +++ b/src/loader/src/launchpad_loader.c @@ -37,11 +37,6 @@ #define PR_TASK_PERF_USER_TRACE 666 #endif -#define KEY_LOADER_TYPE "loader_type" -#define LOADER_TYPE_COMMON "common-loader" -#define LOADER_TYPE_HW "hw-loader" -#define LOADER_TYPE_SW "sw-loader" - #define PATH_LIB_VC_ELM "/usr/lib/libvc-elm.so.0" extern bundle *launchpad_loader_get_bundle(void); -- 2.7.4 From 3e627970ab601d2f93b21536841e34e8fd375dfc Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 21 Feb 2020 12:34:13 +0900 Subject: [PATCH 04/16] Support memory management feature To manage memory usage, the launchpad checks the proc filesystem. If the percentage of memory usage is over the threshold value, the launchpad terminates the running slots. In this time, the running slots are managed by the score and the memory usage(PSS). (exclude hydra loader) The score of the candidate slot is decided by the amount of usage. Change-Id: Ie8678be7dc6dfb346b4523b996bfa39d02b006f5 Signed-off-by: Hwankyu Jhun --- src/launchpad/conf/launchpad.conf.in | 4 + src/launchpad/inc/launchpad_config.h | 2 + src/launchpad/inc/launchpad_memory_monitor.h | 34 ++++ src/launchpad/inc/launchpad_proc.h | 24 +++ src/launchpad/src/launchpad.c | 234 +++++++++++++++++++++++---- src/launchpad/src/launchpad_config.c | 109 ++++++++++--- src/launchpad/src/launchpad_memory_monitor.c | 157 ++++++++++++++++++ src/launchpad/src/launchpad_proc.c | 147 +++++++++++++++++ 8 files changed, 658 insertions(+), 53 deletions(-) create mode 100644 src/launchpad/inc/launchpad_memory_monitor.h create mode 100644 src/launchpad/inc/launchpad_proc.h create mode 100644 src/launchpad/src/launchpad_memory_monitor.c create mode 100644 src/launchpad/src/launchpad_proc.c diff --git a/src/launchpad/conf/launchpad.conf.in b/src/launchpad/conf/launchpad.conf.in index 91fed8c..3615188 100644 --- a/src/launchpad/conf/launchpad.conf.in +++ b/src/launchpad/conf/launchpad.conf.in @@ -3,3 +3,7 @@ LowKey=memory/sysman/low_memory LowValue=2 NormalKey=memory/sysman/low_memory NormalValue=1 + +[MemoryMonitor] +Threshold=80 +Interval=5000 diff --git a/src/launchpad/inc/launchpad_config.h b/src/launchpad/inc/launchpad_config.h index 3b819da..1d2ee1e 100644 --- a/src/launchpad/inc/launchpad_config.h +++ b/src/launchpad/inc/launchpad_config.h @@ -22,6 +22,8 @@ typedef enum { CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE, CONFIG_TYPE_MEMORY_STATUS_NORMAL_KEY, CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE, + CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD, + CONFIG_TYPE_MEMORY_MONITOR_INTERVAL, } config_type_e; const char *_config_get_string_value(config_type_e type); diff --git a/src/launchpad/inc/launchpad_memory_monitor.h b/src/launchpad/inc/launchpad_memory_monitor.h new file mode 100644 index 0000000..a8486be --- /dev/null +++ b/src/launchpad/inc/launchpad_memory_monitor.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LAUNCHPAD_MEMORY_MONITOR_H__ +#define __LAUNCHPAD_MEMORY_MONITOR_H__ + +#include + +typedef int (*memory_monitor_cb)(bool low_memory, void *user_data); + +int _memory_monitor_init(void); + +void _memory_monitor_fini(void); + +int _memory_monitor_set_event_cb(memory_monitor_cb callback, void *user_data); + +int _memory_monitor_reset_timer(void); + +bool _memory_monitor_is_low_memory(void); + +#endif /* __LAUNCHPAD_MEMORY_MONITOR_H__ */ diff --git a/src/launchpad/inc/launchpad_proc.h b/src/launchpad/inc/launchpad_proc.h new file mode 100644 index 0000000..eaff0f6 --- /dev/null +++ b/src/launchpad/inc/launchpad_proc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LAUNCHPAD_PROC_H__ +#define __LAUNCHPAD_PROC_H__ + +int _proc_get_mem_used_ratio(unsigned int *mem_used_ratio); + +int _proc_get_mem_pss(int pid, unsigned int *mem_pss); + +#endif /* __LAUNCHPAD_PROC_H__ */ diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index f1a7d09..487da6e 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -44,12 +44,14 @@ #include "launchpad_common.h" #include "launchpad_config.h" #include "launchpad_debug.h" +#include "launchpad_inotify.h" #include "launchpad_io_channel.h" +#include "launchpad_memory_monitor.h" +#include "launchpad_proc.h" #include "launchpad_signal.h" #include "launchpad_types.h" #include "loader_info.h" #include "perf.h" -#include "launchpad_inotify.h" #define AUL_PR_NAME 16 #define EXEC_CANDIDATE_EXPIRED 5 @@ -74,6 +76,8 @@ #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, @@ -114,6 +118,8 @@ typedef struct { io_channel_h client_channel; io_channel_h channel; io_channel_h hydra_channel; + unsigned int score; + unsigned int pss; } candidate_process_context_t; typedef struct { @@ -177,7 +183,8 @@ 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); +static void __update_slot_state(candidate_process_context_t *cpc, int method, + bool force); static void __init_app_defined_loader_monitor(void); static gboolean __handle_queuing_slots(gpointer data) @@ -424,6 +431,106 @@ static candidate_process_context_t *__find_slot(int type, int 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_last_running_slot(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) + break; + + iter = g_list_previous(iter); + } + + if (!cpc) + return; + + __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, true); +} + +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, false); + + iter = g_list_next(iter); + } +} + static void __kill_process(int pid) { char err_str[MAX_LOCAL_BUFSZ] = { 0, }; @@ -671,7 +778,7 @@ 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); + __update_slot_state(cpc, METHOD_TTL, false); _D("Deactivate event: type(%d)", cpc->type); return G_SOURCE_REMOVE; @@ -761,6 +868,8 @@ static int __prepare_candidate_process(int type, int loader_id) __set_live_timer(cpt); } + _memory_monitor_reset_timer(); + return 0; } @@ -865,6 +974,8 @@ static int __send_launchpad_loader(candidate_process_context_t *cpc, cpc->pid = CANDIDATE_NONE; __dispose_candidate_process(cpc); __set_timer(cpc); + __update_slot_score(cpc); + return pid; } @@ -1806,34 +1917,53 @@ static int __dispatch_cmd_update_app_type(bundle *b) return 0; } -static void __update_slot_state(candidate_process_context_t *cpc, int method) +static void __deactivate_slot(candidate_process_context_t *cpc) { - if (method == METHOD_OUT_OF_MEMORY) { - if ((cpc->deactivation_method & method) && __is_low_memory()) { - cpc->state = CANDIDATE_PROCESS_STATE_PAUSED; - __dispose_candidate_process(cpc); - } else { - cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; - if (!cpc->touched && !cpc->on_boot) - return; - if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE) - return; - if (cpc->detection_method & METHOD_TIMEOUT) - __set_timer(cpc); - } - } else if (cpc->activation_method & method) { - __update_slot_state(cpc, METHOD_OUT_OF_MEMORY); - } else if (cpc->deactivation_method & method) { - cpc->state = CANDIDATE_PROCESS_STATE_PAUSED; - __dispose_candidate_process(cpc); - } else { - cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; - if (!cpc->touched && !cpc->on_boot) - return; - if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE) - return; - if (cpc->detection_method & METHOD_TIMEOUT) - __set_timer(cpc); + if (cpc->state == CANDIDATE_PROCESS_STATE_PAUSED) + return; + + cpc->state = CANDIDATE_PROCESS_STATE_PAUSED; + __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_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()) + __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: + case METHOD_REQUEST: + __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force); + break; + default: + __activate_slot(cpc); + break; } } @@ -1999,7 +2129,7 @@ static bool __handle_launch_event(int fd, io_condition_e cond, void *data) org_cpc->timer = 0; } - __update_slot_state(org_cpc, METHOD_REQUEST); + __update_slot_state(org_cpc, METHOD_REQUEST, true); __set_timer(org_cpc); } } else { @@ -2007,6 +2137,7 @@ static bool __handle_launch_event(int fd, io_condition_e cond, void *data) pid = __send_launchpad_loader(cpc, pkt, app_path, clifd); } + _memory_monitor_reset_timer(); __send_result_to_caller(clifd, pid, app_path); clifd = -1; end: @@ -2109,6 +2240,8 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, cpc->ttl = ttl; cpc->live_timer = 0; cpc->is_hydra = is_hydra; + cpc->score = WIN_SCORE; + cpc->pss = 0; if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) && __is_low_memory()) @@ -2482,8 +2615,12 @@ static void __add_app_defined_loaders(void) 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; } @@ -2512,7 +2649,7 @@ static void __memory_status_low_changed_cb(keynode_t *node, void *data) iter = candidate_slot_list; while (iter) { cpc = (candidate_process_context_t *)iter->data; - __update_slot_state(cpc, METHOD_OUT_OF_MEMORY); + __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, false); iter = g_list_next(iter); } } @@ -2529,7 +2666,7 @@ static void __memory_status_normal_changed_cb(keynode_t *node, void *data) iter = candidate_slot_list; while (iter) { cpc = (candidate_process_context_t *)iter->data; - __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY); + __update_slot_state(cpc, METHOD_AVAILABLE_MEMORY, true); iter = g_list_next(iter); } } @@ -2664,6 +2801,34 @@ static int __init_logger_fd(void) return 0; } +static int __memory_monitor_cb(bool low_memory, void *user_data) +{ + candidate_process_context_t *cpc; + + cpc = __get_running_slot(false); + if (!cpc && low_memory) + return -1; + + __update_slots_pss(); + + candidate_slot_list = g_list_sort(candidate_slot_list, __compare_slot); + + _W("low memory(%s)", low_memory ? "true" : "false"); + if (low_memory) { + do { + __pause_last_running_slot(false); + + cpc = __get_running_slot(false); + if (!cpc) + break; + } while (__is_low_memory()); + } else { + __resume_all_slots(); + } + + return 0; +} + static int __before_loop(int argc, char **argv) { int ret; @@ -2720,12 +2885,15 @@ static int __before_loop(int argc, char **argv) __register_vconf_events(); __init_app_defined_loader_monitor(); + _memory_monitor_init(); + _memory_monitor_set_event_cb(__memory_monitor_cb, NULL); return 0; } static void __after_loop(void) { + _memory_monitor_fini(); __unregister_vconf_events(); if (__pid_table) g_hash_table_destroy(__pid_table); diff --git a/src/launchpad/src/launchpad_config.c b/src/launchpad/src/launchpad_config.c index 8c74693..5b517b0 100644 --- a/src/launchpad/src/launchpad_config.c +++ b/src/launchpad/src/launchpad_config.c @@ -36,6 +36,10 @@ #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" + struct memory_status_s { char *low_key; int low_value; @@ -43,7 +47,13 @@ struct memory_status_s { int normal_value; }; +struct memory_monitor_s { + int threshold; + int interval; +}; + static struct memory_status_s __memory_status; +static struct memory_monitor_s __memory_monitor; const char *_config_get_string_value(config_type_e type) { @@ -76,6 +86,12 @@ int _config_get_int_value(config_type_e type) 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; default: _E("Unknown type"); value = INT_MIN; @@ -102,31 +118,27 @@ static int __get_int_value(dictionary *d, const char *tag, return iniparser_getint(d, buf, INT_MIN); } -int _config_init(void) +static void __memory_status_init(void) { - dictionary *d; - char *val; - const char *str; - int ret; - - _D("config init"); - __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; +} - ret = access(PATH_LAUNCHPAD_CONF, F_OK); - if (ret != 0) { - _W("The file doesn't exist. errno(%d)", errno); - return 0; - } +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); +} - d = iniparser_load(PATH_LAUNCHPAD_CONF); - if (!d) { - _E("Failed to load the config file"); - return -1; - } +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); @@ -163,6 +175,63 @@ int _config_init(void) __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); +} + +int _config_init(void) +{ + dictionary *d; + int ret; + + _D("config init"); + + __memory_status_init(); + __memory_monitor_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); iniparser_freedict(d); @@ -173,6 +242,6 @@ void _config_fini(void) { _D("config fini"); - free(__memory_status.normal_key); - free(__memory_status.low_key); + __memory_monitor_fini(); + __memory_status_fini(); } diff --git a/src/launchpad/src/launchpad_memory_monitor.c b/src/launchpad/src/launchpad_memory_monitor.c new file mode 100644 index 0000000..c6e0d2c --- /dev/null +++ b/src/launchpad/src/launchpad_memory_monitor.c @@ -0,0 +1,157 @@ +/* + * 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; + 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) +{ + unsigned int mem_used_ratio = 0; + int ret; + + __monitor.tag = 0; + ret = _proc_get_mem_used_ratio(&mem_used_ratio); + if (ret != 0) { + _E("Failed to get mem used ratio"); + __monitor.interval = __monitor.base_interval; + __memory_monitor_start(); + return G_SOURCE_REMOVE; + } + + if (__monitor.callback) { + ret = __monitor.callback(mem_used_ratio > __monitor.threshold, + __monitor.user_data); + if (ret == 0) { + _W("Reset interval"); + __monitor.interval = __monitor.base_interval; + } + } + + _W("previous used ratio(%u), current used ratio(%u)", + __monitor.prev_used_ratio, mem_used_ratio); + + __monitor.prev_used_ratio = mem_used_ratio; + __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.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; + + _proc_get_mem_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/src/launchpad_proc.c b/src/launchpad/src/launchpad_proc.c new file mode 100644 index 0000000..daad003 --- /dev/null +++ b/src/launchpad/src/launchpad_proc.c @@ -0,0 +1,147 @@ +/* + * 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_proc.h" +#include "log_private.h" + +#define auto_ptr(x) __attribute__ ((__cleanup__(x))) + +static unsigned int __convert_string(const char *str) +{ + while (*str < '0' || *str > '9') + str++; + + return atoi(str); +} + +static int __open_file(const char *file, FILE **fp) +{ + int ret; + + *fp = fopen(file, "r"); + if (!*fp) { + ret = -errno; + _E("Failed to open %s. errno(%d)", file, errno); + return ret; + } + + return 0; +} + +static void __close_file(FILE **fp) +{ + if (!fp || !*fp) + return; + + fclose(*fp); +} + +int _proc_get_mem_used_ratio(unsigned int *mem_used_ratio) +{ + auto_ptr(__close_file) FILE *fp = NULL; + char buf[LINE_MAX]; + char *str; + unsigned int mem_free = 0; + unsigned int mem_total = 0; + unsigned int mem_available = 0; + unsigned int cached = 0; + unsigned int used; + unsigned int used_ratio; + int ret; + + if (!mem_used_ratio) { + _E("Invalid parameter"); + return -EINVAL; + } + + ret = __open_file("/proc/meminfo", &fp); + if (ret != 0) + return ret; + + while (fgets(buf, sizeof(buf), fp) != NULL) { + if ((str = strstr(buf, "MemTotal:"))) { + str += strlen("MemTotal:"); + mem_total = __convert_string(str); + } else if ((str = strstr(buf, "MemFree:"))) { + str += strlen("MemFree:"); + mem_free = __convert_string(str); + } else if ((str = strstr(buf, "MemAvailable:"))) { + str += strlen("MemAvailable:"); + mem_available = __convert_string(str); + } else if ((str = strstr(buf, "Cached:")) && + !strstr(buf, "Swap")) { + str += strlen("Cached:"); + cached = atoi(str); + break; + } + } + + if (mem_total == 0) { + _E("Failed to get total memory size"); + return -1; + } + + if (mem_available == 0) + mem_available = mem_free + cached; + + used = mem_total - mem_available; + used_ratio = used * 100 / mem_total; + _I("memory used ratio: %u %%", used_ratio); + + *mem_used_ratio = used_ratio; + + return 0; +} + +int _proc_get_mem_pss(int pid, unsigned int *mem_pss) +{ + auto_ptr(__close_file) FILE *fp = NULL; + char path[PATH_MAX]; + char buf[LINE_MAX]; + unsigned int pss = 0; + unsigned int total_pss = 0; + int ret; + + if (pid < 1 || !mem_pss) { + _E("Invalid parameter"); + return -EINVAL; + } + + snprintf(path, sizeof(path), "/proc/%d/smaps", pid); + ret = __open_file(path, &fp); + if (ret != 0) + return ret; + + while (fgets(buf, sizeof(buf), fp) != NULL) { + if (sscanf(buf, "Pss: %d kB", &pss) == 1) { + total_pss += pss; + pss = 0; + } + } + + *mem_pss = total_pss; + _I("[%d] PSS: %u kB", pid, total_pss); + + return 0; +} -- 2.7.4 From bd2006221b4336fd527a0a09984f1c35e6034942 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 25 Feb 2020 09:43:15 +0900 Subject: [PATCH 05/16] Add memory management feature on app-defined-loader If PSS of app-defined-loader process is over the threshold, app-defined-loader process stops loading the libraries. The platform developer can change the threshold using app-defined-loader.conf file. Change-Id: Id2476dbcfbce5d3c272028a883ec6a509cfa310f Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 1 + src/CMakeLists.txt | 2 +- .../CMakeLists.txt | 13 ++- .../conf/app-defined-loader.conf.in | 2 + .../src/app-defined-loader.cc} | 96 ++++++++++++++-------- src/app-defined-loader/src/config.cc | 36 ++++++++ src/app-defined-loader/src/config.hh | 40 +++++++++ src/app-defined-loader/src/log-private.hh | 47 +++++++++++ src/app-defined-loader/src/proc.cc | 50 +++++++++++ src/app-defined-loader/src/proc.hh | 37 +++++++++ 10 files changed, 284 insertions(+), 40 deletions(-) rename src/{app_defined_loader => app-defined-loader}/CMakeLists.txt (89%) create mode 100644 src/app-defined-loader/conf/app-defined-loader.conf.in rename src/{app_defined_loader/src/app_defined_loader.cc => app-defined-loader/src/app-defined-loader.cc} (79%) create mode 100644 src/app-defined-loader/src/config.cc create mode 100644 src/app-defined-loader/src/config.hh create mode 100644 src/app-defined-loader/src/log-private.hh create mode 100644 src/app-defined-loader/src/proc.cc create mode 100644 src/app-defined-loader/src/proc.hh diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 5935833..581b221 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -172,6 +172,7 @@ ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.targ %files -n app-defined-loader %manifest app-defined-loader.manifest %license LICENSE +%{_prefix}/share/aul/app-defined-loader.conf %{_bindir}/app-defined-loader %files -n liblaunchpad diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dbab7f3..352038e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) ADD_SUBDIRECTORY(launchpad) ADD_SUBDIRECTORY(lib) ADD_SUBDIRECTORY(loader) -ADD_SUBDIRECTORY(app_defined_loader) +ADD_SUBDIRECTORY(app-defined-loader) ADD_SUBDIRECTORY(hydra) ADD_SUBDIRECTORY(parser) diff --git a/src/app_defined_loader/CMakeLists.txt b/src/app-defined-loader/CMakeLists.txt similarity index 89% rename from src/app_defined_loader/CMakeLists.txt rename to src/app-defined-loader/CMakeLists.txt index b0f869e..3410782 100644 --- a/src/app_defined_loader/CMakeLists.txt +++ b/src/app-defined-loader/CMakeLists.txt @@ -4,13 +4,14 @@ SET(APP_DEFINED_LOADER "app-defined-loader") INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(APP_DEFINED_LOADER_PKGS REQUIRED + aul + bundle + dbus-1 dlog ecore ecore-core - bundle - aul gio-2.0 - dbus-1 + iniparser libsystemd ) @@ -66,4 +67,8 @@ SET_TARGET_PROPERTIES(${APP_DEFINED_LOADER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFL SET_TARGET_PROPERTIES(${APP_DEFINED_LOADER} PROPERTIES SKIP_BUILD_RPATH TRUE ) # remove rpath option that is automatically generated by cmake. -INSTALL(TARGETS ${APP_DEFINED_LOADER} DESTINATION bin) \ No newline at end of file +INSTALL(TARGETS ${APP_DEFINED_LOADER} DESTINATION bin) + +CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/conf/app-defined-loader.conf.in + ${CMAKE_CURRENT_SOURCE_DIR}/conf/app-defined-loader.conf @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/conf/app-defined-loader.conf DESTINATION share/aul) diff --git a/src/app-defined-loader/conf/app-defined-loader.conf.in b/src/app-defined-loader/conf/app-defined-loader.conf.in new file mode 100644 index 0000000..8381685 --- /dev/null +++ b/src/app-defined-loader/conf/app-defined-loader.conf.in @@ -0,0 +1,2 @@ +[Memory] +Threshold=25600 diff --git a/src/app_defined_loader/src/app_defined_loader.cc b/src/app-defined-loader/src/app-defined-loader.cc similarity index 79% rename from src/app_defined_loader/src/app_defined_loader.cc rename to src/app-defined-loader/src/app-defined-loader.cc index 39ba7d1..873f52b 100644 --- a/src/app_defined_loader/src/app_defined_loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -14,11 +14,12 @@ * limitations under the License. */ -#include -#include -#include #include #include +#include +#include +#include +#include #include #include @@ -26,15 +27,14 @@ #include #include +#include "key.h" +#include "launchpad.h" #include "launchpad_common.h" #include "launchpad_types.h" -#include "launchpad.h" -#include "key.h" -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "APP_DEFINED_LOADER" +#include "config.hh" +#include "log-private.hh" +#include "proc.hh" #ifndef PR_TASK_PERF_USER_TRACE #define PR_TASK_PERF_USER_TRACE 666 @@ -44,35 +44,49 @@ #define C_EXPORT extern "C" __attribute__((visibility("default"))) #endif -using namespace tizen_base; -using namespace std; namespace launchpad { +static const char PATH_CONF[] = "/usr/share/aul/app-defined-loader.conf"; +static const char SECTION_MEMORY[] = "Memory"; +static const char KEY_THRESHOLD[] = "Threshold"; +static uint32_t DEFAULT_THRESHOLD = 25600; // kB + class AppDefinedLoader { public: AppDefinedLoader(int argc, char** argv) : argc_(argc), argv_(argv) { - lifecycle_cb_ = shared_ptr(new loader_lifecycle_callback_s()); + lifecycle_cb_ = std::shared_ptr( + new loader_lifecycle_callback_s()); lifecycle_cb_->create = OnCreate; lifecycle_cb_->launch = OnLaunch; lifecycle_cb_->terminate = OnTerminate; - adapter_ = shared_ptr(new loader_adapter_s()); + adapter_ = std::shared_ptr(new loader_adapter_s()); adapter_->loop_begin = OnLoopBegin; adapter_->loop_quit = OnLoopQuit; adapter_->add_fd = OnAddFd; adapter_->remove_fd = OnRemoveFd; + + proc_ = std::unique_ptr(new Proc(getpid())); + + Config conf(PATH_CONF); + int threshold = conf.GetIntValue(SECTION_MEMORY, KEY_THRESHOLD); + if (threshold > 0) { + threshold_ = static_cast(threshold); + } else { + _W("Failed to get threshold"); + } } ~AppDefinedLoader() { _W("app defined loader destroyed"); } - shared_ptr GetLifeCycle() { + std::shared_ptr GetLifeCycle() { return lifecycle_cb_; } - shared_ptr GetAdapter() { + std::shared_ptr GetAdapter() { return adapter_; } @@ -109,10 +123,11 @@ class AppDefinedLoader { } private: - static void PreloadLib(Bundle data) { - vector so_array = data.GetStringArray("preload"); + void PreloadLib(tizen_base::Bundle data) { + std::vector so_array = data.GetStringArray("preload"); if (so_array.size() == 0) return; + for (auto& i : so_array) { if (i.empty()) continue; @@ -121,14 +136,20 @@ class AppDefinedLoader { _E("fail to load : %s, err : %s", i.c_str(), dlerror()); else _D("preload %s# - handle : %p", i.c_str(), handle); + + uint32_t pss = proc_->GetPss(); + if (pss > threshold_) { + _W("Pss(%u) is over threshold(%u)", pss, threshold_); + break; + } } } static void OnCreate(bundle *extra, int type, void *user_data) { _I("on create"); AppDefinedLoader* loader = (AppDefinedLoader*)user_data; - Bundle ex = Bundle(extra, false, false); - string loader_type = ex.GetString(KEY_LOADER_TYPE); + tizen_base::Bundle ex = tizen_base::Bundle(extra, false, false); + std::string loader_type = ex.GetString(KEY_LOADER_TYPE); if (loader_type.empty()) { _E("No loader type"); return; @@ -147,7 +168,8 @@ class AppDefinedLoader { } static int OnLaunch(int argc, char **argv, const char *app_path, - const char *appid, const char *pkgid, const char *pkg_type, void *user_data) { + const char *appid, const char *pkgid, const char *pkg_type, + void *user_data) { _I("on launch"); AppDefinedLoader* loader = (AppDefinedLoader*)user_data; if (!loader->IsPriorityChangeEnabled()) @@ -157,19 +179,20 @@ class AppDefinedLoader { if (kb == nullptr) return 0; - Bundle data(kb, false, false); - string high_priority = data.GetString(AUL_K_HIGHPRIORITY); + tizen_base::Bundle data(kb, false, false); + std::string high_priority = data.GetString(AUL_K_HIGHPRIORITY); if (high_priority == "true") launchpad_loader_set_priority(-12); data.Delete(AUL_K_HIGHPRIORITY); return 0; } - void DoExec(string libdir) { + void DoExec(std::string libdir) { _I("do exec"); char err_str[MAX_LOCAL_BUFSZ]; if (access(argv_[LOADER_ARG_PATH], F_OK | R_OK)) { - SECURE_LOGE("access() failed for file: \"%s\", error: %d (%s)", argv_[LOADER_ARG_PATH], errno, + SECURE_LOGE("access() failed for file: \"%s\", error: %d (%s)", + argv_[LOADER_ARG_PATH], errno, strerror_r(errno, err_str, sizeof(err_str))); } else { SECURE_LOGD("[candidate] Exec application (%s)", @@ -187,9 +210,10 @@ class AppDefinedLoader { } } - int DoDlOpen(bool restore, string old_cwd, string libdir) { + int DoDlOpen(bool restore, std::string old_cwd, std::string libdir) { _I("do dlopen"); - string hwc_message = "" + to_string(getpid()) + "|lib loading start"; + std::string hwc_message = "" + std::to_string(getpid()) + + "|lib loading start"; prctl(PR_TASK_PERF_USER_TRACE, hwc_message.c_str(), hwc_message.size()); void* handle = dlopen(argv_[LOADER_ARG_PATH], RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE); @@ -199,7 +223,7 @@ class AppDefinedLoader { return -1; } - hwc_message = "" + to_string(getpid()) + "|lib loading end"; + hwc_message = "" + std::to_string(getpid()) + "|lib loading end"; prctl(PR_TASK_PERF_USER_TRACE, hwc_message.c_str(), hwc_message.size()); if (restore && chdir(old_cwd.c_str())) @@ -218,7 +242,8 @@ class AppDefinedLoader { } static int OnTerminate(int argc, char **argv, void *user_data) { - SECURE_LOGD("[candidate] Launch real application (%s)", argv[LOADER_ARG_PATH]); + SECURE_LOGD("[candidate] Launch real application (%s)", + argv[LOADER_ARG_PATH]); char old_cwd[PATH_MAX] = {0, }; AppDefinedLoader* loader = (AppDefinedLoader*)user_data; if (getcwd(old_cwd, sizeof(old_cwd)) == nullptr) { @@ -237,7 +262,7 @@ class AppDefinedLoader { _E("failed to chdir: %d", errno); else restore = true; - string libdir_str = string(libdir); + std::string libdir_str = std::string(libdir); free(libdir); return loader->DoDlOpen(restore, old_cwd, libdir_str); } @@ -302,20 +327,21 @@ class AppDefinedLoader { } private: - shared_ptr lifecycle_cb_ = nullptr; - shared_ptr adapter_ = nullptr; + std::shared_ptr lifecycle_cb_ = nullptr; + std::shared_ptr adapter_ = nullptr; bool loader_priority_enabled_ = false; bool priority_change_enabled_ = false; - loader_receiver_cb receiver_cb_; + loader_receiver_cb receiver_cb_ = nullptr; Ecore_Fd_Handler* fd_handler_ = nullptr; + std::unique_ptr proc_; + uint32_t threshold_ = DEFAULT_THRESHOLD; int argc_; char** argv_; }; } -C_EXPORT int main(int argc, char **argv) -{ +C_EXPORT int main(int argc, char **argv) { launchpad::AppDefinedLoader loader(argc, argv); #ifdef TIZEN_FEATURE_LOADER_PRIORITY @@ -327,4 +353,4 @@ C_EXPORT int main(int argc, char **argv) return launchpad_loader_main(argc, argv, loader.GetLifeCycle().get(), loader.GetAdapter().get(), &loader); -} \ No newline at end of file +} diff --git a/src/app-defined-loader/src/config.cc b/src/app-defined-loader/src/config.cc new file mode 100644 index 0000000..2a03202 --- /dev/null +++ b/src/app-defined-loader/src/config.cc @@ -0,0 +1,36 @@ +/* + * 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 "config.hh" + +namespace launchpad { + +Config::Config(const std::string& path) + : d_(iniparser_load(path.c_str()), iniparser_freedict) { +} + +Config::~Config() = default; + +int Config::GetIntValue(const std::string& section, + const std::string& key) const { + std::string section_key = section + ":" + key; + + return iniparser_getint(d_.get(), section_key.c_str(), INT_MIN); +} + +} // namespace launchpad diff --git a/src/app-defined-loader/src/config.hh b/src/app-defined-loader/src/config.hh new file mode 100644 index 0000000..3e12bdf --- /dev/null +++ b/src/app-defined-loader/src/config.hh @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CONFIG_HH_ +#define CONFIG_HH_ + +#include + +#include + +namespace launchpad { + +class Config { + public: + Config(const std::string& path); + virtual ~Config(); + + public: + int GetIntValue(const std::string& section, const std::string& key) const; + + private: + std::unique_ptr d_; +}; + +} // namespace launchpad + +#endif // CONFIG_HH_ diff --git a/src/app-defined-loader/src/log-private.hh b/src/app-defined-loader/src/log-private.hh new file mode 100644 index 0000000..ee448ce --- /dev/null +++ b/src/app-defined-loader/src/log-private.hh @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LOG_PRIVATE_HH_ +#define LOG_PRIVATE_HH_ + +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "APP_DEFINED_LOADER" + +#ifdef _E +#undef _E +#endif +#define _E LOGE + +#ifdef _W +#undef _W +#endif +#define _W LOGW + +#ifdef _I +#undef _I +#endif +#define _I LOGI + +#ifdef _D +#undef _D +#endif +#define _D LOGD + +#endif // LOG_PRIVATE_HH_ diff --git a/src/app-defined-loader/src/proc.cc b/src/app-defined-loader/src/proc.cc new file mode 100644 index 0000000..9719cea --- /dev/null +++ b/src/app-defined-loader/src/proc.cc @@ -0,0 +1,50 @@ +/* + * 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 "log-private.hh" +#include "proc.hh" + +namespace launchpad { + +Proc::Proc(int pid) : pid_(pid) { +} + +Proc::~Proc() = default; + +uint32_t Proc::GetPss() const { + uint32_t total_pss = 0; + std::string path = "/proc/" + std::to_string(pid_) + "/smaps"; + std::ifstream stream(path); + if (stream.is_open()) { + std::string line; + while (std::getline(stream, line)) { + uint32_t pss = 0; + if (std::sscanf(line.c_str(), "Pss: %u kB", &pss) == 1) { + total_pss += pss; + pss = 0; + } + } + stream.close(); + } + + _I("Pss: %u kB", total_pss); + return total_pss; +} + +} // namespace launchpad diff --git a/src/app-defined-loader/src/proc.hh b/src/app-defined-loader/src/proc.hh new file mode 100644 index 0000000..4ffb1a5 --- /dev/null +++ b/src/app-defined-loader/src/proc.hh @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROC_HH_ +#define PROC_HH_ + +#include + +namespace launchpad { + +class Proc { + public: + Proc(int pid); + virtual ~Proc(); + + uint32_t GetPss() const; + + private: + int pid_; +}; + +} // namespace launchpad + +#endif // PROC_HH_ -- 2.7.4 From 37df24dab41b16c697e3e28d54b171d0e218c30e Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 25 Feb 2020 10:12:43 +0900 Subject: [PATCH 06/16] Fix memory management feature Change-Id: Icff15a3b5e9b16e3e3e0572a1cbdb8daa673e2b9 Signed-off-by: Hwankyu Jhun --- src/launchpad/src/launchpad.c | 15 ++++++++++----- src/launchpad/src/launchpad_memory_monitor.c | 8 ++------ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 487da6e..4d8bbd3 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -1958,8 +1958,12 @@ static void __update_slot_state(candidate_process_context_t *cpc, int method, __deactivate_slot(cpc); break; case METHOD_AVAILABLE_MEMORY: + if (force || cpc->activation_method & method) + __activate_slot(cpc); + break; case METHOD_REQUEST: - __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force); + if (force || cpc->activation_method & method) + __update_slot_state(cpc, METHOD_OUT_OF_MEMORY, force); break; default: __activate_slot(cpc); @@ -2805,16 +2809,17 @@ static int __memory_monitor_cb(bool low_memory, void *user_data) { candidate_process_context_t *cpc; + _W("low memory(%s)", low_memory ? "true" : "false"); cpc = __get_running_slot(false); if (!cpc && low_memory) return -1; - __update_slots_pss(); + if (low_memory) { + __update_slots_pss(); - candidate_slot_list = g_list_sort(candidate_slot_list, __compare_slot); + candidate_slot_list = g_list_sort(candidate_slot_list, + __compare_slot); - _W("low memory(%s)", low_memory ? "true" : "false"); - if (low_memory) { do { __pause_last_running_slot(false); diff --git a/src/launchpad/src/launchpad_memory_monitor.c b/src/launchpad/src/launchpad_memory_monitor.c index c6e0d2c..dacf3ab 100644 --- a/src/launchpad/src/launchpad_memory_monitor.c +++ b/src/launchpad/src/launchpad_memory_monitor.c @@ -57,15 +57,11 @@ static gboolean __memory_check_cb(gpointer data) } if (__monitor.callback) { - ret = __monitor.callback(mem_used_ratio > __monitor.threshold, + __monitor.callback(mem_used_ratio > __monitor.threshold, __monitor.user_data); - if (ret == 0) { - _W("Reset interval"); - __monitor.interval = __monitor.base_interval; - } } - _W("previous used ratio(%u), current used ratio(%u)", + _D("previous used ratio(%u), current used ratio(%u)", __monitor.prev_used_ratio, mem_used_ratio); __monitor.prev_used_ratio = mem_used_ratio; -- 2.7.4 From acc6be19d391a3d71c63ddbb8e4fa9b91aa91dfe Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 25 Feb 2020 10:46:17 +0900 Subject: [PATCH 07/16] Adjust coding style - Uses static_cast<...>(...) instead of C-style cast - Uses left alignment style - Adds C++ coding style check tool Change-Id: I5b0a7817fe9f523027b1a8ee4c2fe4eb5b05d236 Signed-off-by: Hwankyu Jhun --- src/app-defined-loader/src/app-defined-loader.cc | 44 +++++++++++------------- tools/check-coding-style | 28 +++++++++++++++ 2 files changed, 48 insertions(+), 24 deletions(-) create mode 100755 tools/check-coding-style diff --git a/src/app-defined-loader/src/app-defined-loader.cc b/src/app-defined-loader/src/app-defined-loader.cc index 873f52b..38ffb94 100644 --- a/src/app-defined-loader/src/app-defined-loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -40,10 +40,6 @@ #define PR_TASK_PERF_USER_TRACE 666 #endif -#ifndef C_EXPORT -#define C_EXPORT extern "C" __attribute__((visibility("default"))) -#endif - namespace launchpad { static const char PATH_CONF[] = "/usr/share/aul/app-defined-loader.conf"; @@ -145,9 +141,9 @@ class AppDefinedLoader { } } - static void OnCreate(bundle *extra, int type, void *user_data) { + static void OnCreate(bundle* extra, int type, void* user_data) { _I("on create"); - AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + AppDefinedLoader* loader = static_cast(user_data); tizen_base::Bundle ex = tizen_base::Bundle(extra, false, false); std::string loader_type = ex.GetString(KEY_LOADER_TYPE); if (loader_type.empty()) { @@ -167,15 +163,15 @@ class AppDefinedLoader { setenv("AUL_HWACC", "hw", 1); } - static int OnLaunch(int argc, char **argv, const char *app_path, - const char *appid, const char *pkgid, const char *pkg_type, - void *user_data) { + 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 = (AppDefinedLoader*)user_data; + AppDefinedLoader* loader = static_cast(user_data); if (!loader->IsPriorityChangeEnabled()) return 0; - bundle *kb = launchpad_loader_get_bundle(); + bundle* kb = launchpad_loader_get_bundle(); if (kb == nullptr) return 0; @@ -229,7 +225,8 @@ class AppDefinedLoader { if (restore && chdir(old_cwd.c_str())) _E("failed to chdir: %d", errno); - void* dl_main = dlsym(handle, "main"); + auto dl_main = reinterpret_cast( + dlsym(handle, "main")); if (dl_main == nullptr) { _E("dlsym not founded(%s). Please export 'main' function", dlerror()); dlclose(handle); @@ -238,14 +235,14 @@ class AppDefinedLoader { } _I("call main"); - return ((int (*)(int, char**))dl_main)(argc_, argv_); + return dl_main(argc_, argv_); } - static int OnTerminate(int argc, char **argv, void *user_data) { + static int OnTerminate(int argc, char** argv, void* user_data) { SECURE_LOGD("[candidate] Launch real application (%s)", argv[LOADER_ARG_PATH]); char old_cwd[PATH_MAX] = {0, }; - AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + AppDefinedLoader* loader = static_cast(user_data); if (getcwd(old_cwd, sizeof(old_cwd)) == nullptr) { loader->DoDlOpen(false, old_cwd, ""); } else { @@ -280,9 +277,8 @@ class AppDefinedLoader { ecore_main_loop_quit(); } - static void OnAddFd(void* user_data, int fd, - loader_receiver_cb receiver) { - AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + static void OnAddFd(void* user_data, int fd, loader_receiver_cb receiver) { + AppDefinedLoader* loader = static_cast(user_data); Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd, (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR), FdHandler, loader, nullptr, nullptr); @@ -296,9 +292,9 @@ class AppDefinedLoader { loader->SetReceiver(receiver); } - static Eina_Bool FdHandler(void *user_data, Ecore_Fd_Handler *handler) { + static Eina_Bool FdHandler(void* user_data, Ecore_Fd_Handler* handler) { _I("fd handler"); - AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + AppDefinedLoader* loader = static_cast(user_data); int fd = ecore_main_fd_handler_fd_get(handler); if (fd == -1) { _E("[candidate] ECORE_FD_GET"); @@ -316,9 +312,9 @@ class AppDefinedLoader { return ECORE_CALLBACK_CANCEL; } - static void OnRemoveFd(void *user_data, int fd) { + static void OnRemoveFd(void* user_data, int fd) { _I("remove fd"); - AppDefinedLoader* loader = (AppDefinedLoader*)user_data; + AppDefinedLoader* loader = static_cast(user_data); if (loader->GetFdHandler() == nullptr) return; ecore_main_fd_handler_del(loader->GetFdHandler()); @@ -339,9 +335,9 @@ class AppDefinedLoader { char** argv_; }; -} +} // namespace launchpad -C_EXPORT int main(int argc, char **argv) { +int main(int argc, char** argv) { launchpad::AppDefinedLoader loader(argc, argv); #ifdef TIZEN_FEATURE_LOADER_PRIORITY diff --git a/tools/check-coding-style b/tools/check-coding-style new file mode 100755 index 0000000..fd60481 --- /dev/null +++ b/tools/check-coding-style @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +if [ ! `which cpplint.py` ]; then + echo -e "\nPlease make sure cpplint.py is in your PATH. It is part of depot_tools inside Chromium repository." + exit 1 +fi + +OLDPWD=$PWD +BASE=`dirname $0` +cd $BASE/.. + +# filters +FILTERS="-readability/streams,-build/c++11" + +cpplint.py --root=src --filter="$FILTERS" $(find . \( -name '*.h' -o -name '*.cc' \) ) +RET=$? + +JS_RET_VAL=$? +cd $OLDPWD + +if [ "x$RET" == "x0" ]; then + exit 0 +else + exit 1 +fi -- 2.7.4 From 726fdb6eb52f6e78912e59823a96a7f2a38bc058 Mon Sep 17 00:00:00 2001 From: Jusung Son Date: Tue, 25 Feb 2020 11:30:47 +0900 Subject: [PATCH 08/16] Fix char overflow char type_str[0] = '0' + LAUNCHPAD_LOADER_TYPE_DYNAMIC = 48 + 100 = -108 Change-Id: Ifebba27e34d303fcdbaf5205471d39c91c1dbcbc Signed-off-by: Jusung Son --- src/launchpad/src/launchpad.c | 6 +++--- src/lib/src/launchpad_lib.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 4d8bbd3..3032e22 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -828,8 +828,8 @@ static int __hydra_send_launch_candidate_request(int fd) static int __prepare_candidate_process(int type, int loader_id) { int pid; - char type_str[2] = {0, }; - char loader_id_str[10] = {0, }; + char type_str[12] = {0, }; + char loader_id_str[12] = {0, }; char argbuf[LOADER_ARG_LEN]; char *argv[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; candidate_process_context_t *cpt = __find_slot(type, loader_id); @@ -847,8 +847,8 @@ static int __prepare_candidate_process(int type, int loader_id) cpt->last_exec_time = time(NULL); - type_str[0] = '0' + type; snprintf(loader_id_str, sizeof(loader_id_str), "%d", loader_id); + snprintf(type_str, sizeof(type_str), "%d", type); argv[LOADER_ARG_PATH] = cpt->loader_path; argv[LOADER_ARG_TYPE] = type_str; argv[LOADER_ARG_ID] = loader_id_str; diff --git a/src/lib/src/launchpad_lib.c b/src/lib/src/launchpad_lib.c index e2a75bc..45a59f9 100644 --- a/src/lib/src/launchpad_lib.c +++ b/src/lib/src/launchpad_lib.c @@ -405,7 +405,7 @@ API int launchpad_loader_main(int argc, char **argv, return -1; } - __loader_type = argv[LOADER_ARG_TYPE][0] - '0'; + __loader_type = atoi(argv[LOADER_ARG_TYPE]); if (__loader_type < 0 || __loader_type >= LAUNCHPAD_TYPE_MAX) { _E("invalid argument. (type: %d)", __loader_type); return -1; -- 2.7.4 From 4507b214c81c33177919383cb31fc3f8e1165aab Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 25 Feb 2020 13:27:50 +0900 Subject: [PATCH 09/16] Release version 0.13.0 Changes: - Add app_defined_loader - Support memory management feature - Add memory management feature on app-defined-loader - Fix memory management feature - Adjust coding style - Fix char overflow Change-Id: Ib77043876d29015c78253717c0a15ea90373b7b4 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 581b221..42fb613 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.12.1 +Version: 0.13.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 1b8896a6ae459b0d8bb507234fbcc58b963b5e2a Mon Sep 17 00:00:00 2001 From: Jusung Son Date: Tue, 25 Feb 2020 14:21:58 +0900 Subject: [PATCH 10/16] Modify candidate process creation rule for app-defined loader - Create only one candidate process for each loader Change-Id: If4a17d2574a8068620eda7e8621c39df5dc38ff0 Signed-off-by: Jusung Son --- src/launchpad/inc/loader_info.h | 2 +- src/launchpad/src/launchpad.c | 96 ++++++++++++++++++++++++++++++----------- src/launchpad/src/loader_info.c | 2 +- 3 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/launchpad/inc/loader_info.h b/src/launchpad/inc/loader_info.h index 2e703b5..5111519 100644 --- a/src/launchpad/inc/loader_info.h +++ b/src/launchpad/inc/loader_info.h @@ -64,7 +64,7 @@ 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); -const loader_info_t* _loader_info_find_loader_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); diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 3032e22..43540d6 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -96,6 +96,7 @@ typedef struct { int hydra_fd; int last_exec_time; guint timer; + char *loader_name; char *loader_path; char *loader_extra; int detection_method; @@ -172,7 +173,8 @@ static io_channel_h __sigchild_channel; static io_channel_h __launchpad_channel; static candidate_process_context_t *__add_slot(int type, int loader_id, - int caller_pid, const char *loader_path, const char *extra, + int caller_pid, const char *loader_name, + const char *loader_path, const char *extra, int detection_method, int activation_method, int deactivation_method, unsigned int ttl, int timeout_val, int threshold_max, int threshold_min, bool on_boot, @@ -423,6 +425,22 @@ static candidate_process_context_t *__find_slot_from_loader_id(int id) 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) @@ -1679,7 +1697,8 @@ static int __dispatch_cmd_add_loader(bundle *kb) const char *add_slot_str = NULL; const char *caller_pid = NULL; const char *extra; - int lid; + int lid, size; + char *loader_name; candidate_process_context_t *cpc; _W("cmd add loader"); @@ -1689,8 +1708,18 @@ static int __dispatch_cmd_add_loader(bundle *kb) if (add_slot_str && caller_pid) { 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); + cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, - atoi(caller_pid), + atoi(caller_pid), loader_name, add_slot_str, extra, METHOD_TIMEOUT | METHOD_VISIBILITY, METHOD_REQUEST | METHOD_AVAILABLE_MEMORY, @@ -1702,6 +1731,7 @@ static int __dispatch_cmd_add_loader(bundle *kb) false, true, 0); __set_timer(cpc); + free(loader_name); return lid; } @@ -1713,7 +1743,7 @@ static int __dispatch_cmd_add_app_defined_loader(bundle *kb) const char *loader_name; int lid, len; candidate_process_context_t *cpc; - const loader_info_t *info; + loader_info_t *info; bundle_raw *extra; _W("cmd add defined loader"); @@ -1733,25 +1763,31 @@ static int __dispatch_cmd_add_app_defined_loader(bundle *kb) bundle_encode(info->extra, &extra, &len); - lid = __make_loader_id(); - cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0, - "/usr/bin/app-defined-loader", (const char *)extra, - METHOD_TIMEOUT | METHOD_VISIBILITY, - METHOD_REQUEST | METHOD_AVAILABLE_MEMORY, - METHOD_TTL | METHOD_OUT_OF_MEMORY, - info->ttl, - 2000, - DEFAULT_CPU_THRESHOLD_MAX, - DEFAULT_CPU_THRESHOLD_MIN, - false, - true, 0); + cpc = __find_slot_from_loader_name(loader_name); if (cpc == NULL) { - _E("cpc is NULL"); - bundle_free_encoded_rawdata(&extra); - return -ENOMEM; + lid = __make_loader_id(); + cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid, 0, + loader_name, "/usr/bin/app-defined-loader", (const char *)extra, + METHOD_TIMEOUT | METHOD_VISIBILITY, + METHOD_REQUEST | METHOD_AVAILABLE_MEMORY, + METHOD_TTL | METHOD_OUT_OF_MEMORY, + info->ttl, + 2000, + DEFAULT_CPU_THRESHOLD_MAX, + DEFAULT_CPU_THRESHOLD_MIN, + false, + true, 0); + if (cpc == NULL) { + _E("cpc is NULL"); + bundle_free_encoded_rawdata(&extra); + return -ENOMEM; + } + } else { + lid = cpc->loader_id; } - __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid); + if (cpc->pid == CANDIDATE_NONE) + __prepare_candidate_process(LAUNCHPAD_LOADER_TYPE_DYNAMIC, lid); return lid; } @@ -2184,11 +2220,14 @@ static void __destroy_slot(candidate_process_context_t *cpc) 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(int type, int loader_id, - int caller_pid, const char *loader_path, + int caller_pid, const char *loader_name, const char *loader_path, const char *loader_extra, int detection_method, int activation_method, int deactivation_method, unsigned int ttl, int timeout_val, @@ -2203,6 +2242,13 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, return NULL; } + cpc->loader_name = strdup(loader_name); + if (cpc->loader_name == NULL) { + _E("Failed to duplicate loader name(%s)", loader_name); + __destroy_slot(cpc); + return NULL; + } + cpc->loader_path = strdup(loader_path); if (cpc->loader_path == NULL) { _E("Failed to duplicate loader path(%s)", loader_path); @@ -2257,7 +2303,7 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, } static candidate_process_context_t *__add_slot(int type, int loader_id, - int caller_pid, const char *loader_path, + int caller_pid, const char *loader_name, const char *loader_path, const char *loader_extra, int detection_method, int activation_method, int deactivation_method, unsigned int ttl, int timeout_val, @@ -2274,7 +2320,7 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, return NULL; cpc = __create_slot(type, loader_id, - caller_pid, loader_path, + caller_pid, loader_name, loader_path, loader_extra, detection_method, activation_method, deactivation_method, ttl, timeout_val, @@ -2555,7 +2601,7 @@ static void __add_slot_from_info(gpointer data, gpointer user_data) if (!strcmp(info->exe, "null")) { cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset, PAD_LOADER_ID_DIRECT, - 0, info->exe, NULL, + 0, info->name, info->exe, NULL, 0, 0, 0, 0, 0, info->cpu_threshold_max, info->cpu_threshold_min, @@ -2578,7 +2624,7 @@ static void __add_slot_from_info(gpointer data, gpointer user_data) cpc = __add_slot(LAUNCHPAD_LOADER_TYPE_USER + user_slot_offset, PAD_LOADER_ID_STATIC, - 0, info->exe, (char *)extra, + 0, info->name, info->exe, (char *)extra, info->detection_method, info->activation_method, info->deactivation_method, diff --git a/src/launchpad/src/loader_info.c b/src/launchpad/src/loader_info.c index 375c1fd..2c5c5da 100644 --- a/src/launchpad/src/loader_info.c +++ b/src/launchpad/src/loader_info.c @@ -385,7 +385,7 @@ const char* _loader_info_find_loader_path_by_loader_name(GList *list, const char return info->exe; } -const loader_info_t* _loader_info_find_loader_by_loader_name(GList *list, const char *loader_name) +loader_info_t* _loader_info_find_loader_by_loader_name(GList *list, const char *loader_name) { GList *cur; loader_info_t *info; -- 2.7.4 From ac554a40cbf710c30fb815e94b084e0b9195acfd Mon Sep 17 00:00:00 2001 From: Jusung Son Date: Tue, 25 Feb 2020 14:26:08 +0900 Subject: [PATCH 11/16] Fix resource leak Change-Id: I480ea356548a4ce25a4e6ebb6028474bd011a950 Signed-off-by: Jusung Son --- src/launchpad/src/launchpad.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 43540d6..79ac8f6 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -2457,6 +2457,9 @@ static bool __on_file_change(const char *event_name, uint32_t mask, { char buf[PATH_MAX]; char *ext; + loader_info_t* info; + candidate_process_context_t *cpc; + if (!event_name) { _E("Invalid parameter"); return true; @@ -2472,7 +2475,12 @@ static bool __on_file_change(const char *event_name, uint32_t mask, 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, "%s", event_name); + 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); } -- 2.7.4 From 4c482bd730a33b5752c87d0b100884622ef26f41 Mon Sep 17 00:00:00 2001 From: Jusung Son Date: Tue, 25 Feb 2020 17:15:32 +0900 Subject: [PATCH 12/16] Apply time-to-live range for app-defined loader - min : 30sec, max 60sec Change-Id: Id31bc158a6841ee3240552e9bc8ccddd91973bc1 Signed-off-by: Jusung Son --- src/parser/loader_info.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/parser/loader_info.cc b/src/parser/loader_info.cc index 1f6a2f5..f2ffdec 100644 --- a/src/parser/loader_info.cc +++ b/src/parser/loader_info.cc @@ -30,6 +30,11 @@ int LoaderInfo::GetTimeToLive() { } void LoaderInfo::SetTimeToLive(int time) { + if (time < 30) + time = 30; + else if (time > 60) + time = 60; + time_to_live_ = time; } -- 2.7.4 From 3b6c6f584e44ce0bf621d387d4945237b8ccc51f Mon Sep 17 00:00:00 2001 From: Jusung Son Date: Wed, 26 Feb 2020 13:32:26 +0900 Subject: [PATCH 13/16] Release version 0.13.1 Changes: - Modify candidate process creation rule for app-defined loader - Fix resource leak - Apply time-to-live range for app-defined loader Change-Id: I2bd0fae505bee9ed5c64c7ff04fdfcf5fdb90a49 Signed-off-by: Jusung Son --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 42fb613..d129b47 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.13.0 +Version: 0.13.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From b5b47fcdbc83499d737b95fbf0e7c9fdb92bf353 Mon Sep 17 00:00:00 2001 From: Jongmin Lee Date: Wed, 8 Apr 2020 09:08:23 +0900 Subject: [PATCH 14/16] Check EFL module version in build time EFL module path depend on its version. This commit makes it possible to read EFL module version and generate EFL module path in build time. Change-Id: I8bcf33dc814878bd0e8900b7c29105a07c2208d9 --- CMakeLists.txt | 5 +++++ packaging/default.loader.in | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7d515c..7fbbd02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,4 +17,9 @@ ADD_DEFINITIONS("-DLAUNCHPAD_LOG") ADD_DEFINITIONS("-DPRELOAD_ACTIVATE") ADD_DEFINITIONS("-DPREEXEC_ACTIVATE") +EXEC_PROGRAM(pkg-config + ARGS --variable=module_arch ecore + OUTPUT_VARIABLE EFL_MODULE_VERSION +) + ADD_SUBDIRECTORY(src) diff --git a/packaging/default.loader.in b/packaging/default.loader.in index a910c96..3e076ce 100644 --- a/packaging/default.loader.in +++ b/packaging/default.loader.in @@ -10,12 +10,12 @@ EXTRA_ARRAY preload EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libappcore-efl.so.1 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/v-1.23/module.so +EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_imf/modules/wayland/@EFL_MODULE_VERSION@/module.so EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libdali-toolkit.so EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libcairo.so.2 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/v-1.23/module.so +EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_evas/engines/extn/@EFL_MODULE_VERSION@/module.so ALTERNATIVE_LOADER common-loader1 [LOADER] @@ -29,8 +29,8 @@ EXTRA_ARRAY preload EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/libappcore-efl.so.1 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/v-1.23/module.so -EXTRA_ARRAY_VAL @LIB_INSTALL_DIR@/ecore_evas/engines/extn/v-1.23/module.so +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 -- 2.7.4 From e4371145601eb5b15d3065b000ba61157bcc623b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 7 Apr 2020 15:26:43 +0900 Subject: [PATCH 15/16] Add a new tag for loader If "APP_CHECK" is "OFF", the launchpad doesn't check whether the application is installed or not. Change-Id: I74aa5c02429c945194113a8a29649d71bf068256 Signed-off-by: Hwankyu Jhun --- src/launchpad/inc/loader_info.h | 1 + src/launchpad/src/launchpad.c | 38 ++++++++++++++++++++++++-------------- src/launchpad/src/loader_info.c | 5 +++++ 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/launchpad/inc/loader_info.h b/src/launchpad/inc/loader_info.h index 5111519..e3ae865 100644 --- a/src/launchpad/inc/loader_info.h +++ b/src/launchpad/inc/loader_info.h @@ -53,6 +53,7 @@ typedef struct _loader_info { int deactivation_method; unsigned int ttl; bool is_hydra; + bool app_check; } loader_info_t; typedef void (*loader_info_foreach_cb)(loader_info_t *info, void *data); diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 79ac8f6..a5931f2 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -116,6 +116,7 @@ typedef struct { 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; @@ -178,7 +179,7 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, int detection_method, int activation_method, int deactivation_method, unsigned int ttl, int timeout_val, int threshold_max, int threshold_min, bool on_boot, - bool app_exists, bool is_hydra); + bool app_exists, bool is_hydra, bool app_check); static int __remove_slot(int type, int loader_id); static int __add_default_slots(void); static gboolean __handle_idle_checker(gpointer data); @@ -211,7 +212,7 @@ static gboolean __handle_queuing_slots(gpointer data) return G_SOURCE_REMOVE;; } - if (!cpc->app_exists) { + if (cpc->app_check && !cpc->app_exists) { _W("The application is not installed. Type(%d)", cpc->type); return G_SOURCE_CONTINUE; } @@ -1601,7 +1602,7 @@ static gboolean __handle_idle_checker(gpointer data) } cpc = (candidate_process_context_t *)data; - if (!cpc->app_exists) { + if (cpc->app_check && !cpc->app_exists) { _W("The application is not installed. Type(%d)", cpc->type); __sequencer.idle_checker = 0; __sequencer.running_cpc = NULL; @@ -1660,7 +1661,7 @@ static int __add_idle_checker(int detection_method, GList *cur) continue; } - if (!cpc->app_exists) { + if (cpc->app_check && !cpc->app_exists) { iter = g_list_next(iter); continue; } @@ -1729,7 +1730,9 @@ static int __dispatch_cmd_add_loader(bundle *kb) DEFAULT_CPU_THRESHOLD_MAX, DEFAULT_CPU_THRESHOLD_MIN, false, - true, 0); + true, + false, + true); __set_timer(cpc); free(loader_name); return lid; @@ -1776,7 +1779,9 @@ static int __dispatch_cmd_add_app_defined_loader(bundle *kb) DEFAULT_CPU_THRESHOLD_MAX, DEFAULT_CPU_THRESHOLD_MIN, false, - true, 0); + true, + false, + true); if (cpc == NULL) { _E("cpc is NULL"); bundle_free_encoded_rawdata(&extra); @@ -1887,7 +1892,7 @@ static void __update_slot(int type, bool app_exists) return; cpc->app_exists = app_exists; - if (!cpc->app_exists) { + if (cpc->app_check && !cpc->app_exists) { if (cpc->pid > 0) __dispose_candidate_process(cpc); __sequencer_remove_slot(cpc); @@ -1971,7 +1976,7 @@ static void __activate_slot(candidate_process_context_t *cpc) if (!cpc->touched && !cpc->on_boot) return; - if (!cpc->app_exists || cpc->pid > CANDIDATE_NONE) + if ((cpc->app_check && !cpc->app_exists) || cpc->pid > CANDIDATE_NONE) return; if (cpc->detection_method & METHOD_TIMEOUT) @@ -2161,7 +2166,7 @@ static bool __handle_launch_event(int fd, io_condition_e cond, void *data) _W("Launch directly %d %p", loader_id, cpc); pid = __launch_directly(menu_info->appid, app_path, clifd, kb, menu_info, NULL); - if (org_cpc && org_cpc->app_exists && + if (org_cpc && (!org_cpc->app_check || org_cpc->app_exists) && org_cpc->pid == CANDIDATE_NONE && !__sequencer_slot_exist(org_cpc)) { if (org_cpc->timer > 0) { @@ -2232,7 +2237,7 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, int activation_method, int deactivation_method, unsigned int ttl, int timeout_val, int threshold_max, int threshold_min, - bool on_boot, bool app_exists, bool is_hydra) + bool on_boot, bool app_exists, bool is_hydra, bool app_check) { candidate_process_context_t *cpc; @@ -2290,6 +2295,7 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, cpc->ttl = ttl; cpc->live_timer = 0; cpc->is_hydra = is_hydra; + cpc->app_check = app_check; cpc->score = WIN_SCORE; cpc->pss = 0; @@ -2308,7 +2314,7 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, int activation_method, int deactivation_method, unsigned int ttl, int timeout_val, int threshold_max, int threshold_min, - bool on_boot, bool app_exists, bool is_hydra) + bool on_boot, bool app_exists, bool is_hydra, bool app_check) { candidate_process_context_t *cpc; int fd; @@ -2325,7 +2331,7 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, activation_method, deactivation_method, ttl, timeout_val, threshold_max, threshold_min, - on_boot, app_exists, is_hydra); + on_boot, app_exists, is_hydra, app_check); if (cpc == NULL) return NULL; @@ -2614,7 +2620,9 @@ static void __add_slot_from_info(gpointer data, gpointer user_data) info->cpu_threshold_max, info->cpu_threshold_min, false, - info->app_exists, info->is_hydra); + info->app_exists, + info->is_hydra, + info->app_check); if (cpc == NULL) return; @@ -2641,7 +2649,9 @@ static void __add_slot_from_info(gpointer data, gpointer user_data) info->cpu_threshold_max, info->cpu_threshold_min, info->on_boot, - info->app_exists, info->is_hydra); + info->app_exists, + info->is_hydra, + info->app_check); if (cpc == NULL) return; diff --git a/src/launchpad/src/loader_info.c b/src/launchpad/src/loader_info.c index 2c5c5da..3493366 100644 --- a/src/launchpad/src/loader_info.c +++ b/src/launchpad/src/loader_info.c @@ -42,6 +42,7 @@ #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 VAL_ON "ON" #define VAL_OFF "OFF" @@ -84,6 +85,7 @@ static loader_info_t *__create_loader_info() info->deactivation_method = 0; info->ttl = 600; /* 10 minutes */ info->is_hydra = false; + info->app_check = true; return info; } @@ -305,6 +307,9 @@ static GList *__parse_file(GList *list, const char *path) } 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; } } -- 2.7.4 From 5f1ebde72a91a0fc6a09a2ae1ec5699ac36796f2 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 8 Apr 2020 12:33:46 +0900 Subject: [PATCH 16/16] Release version 0.14.0 Changes: - Check EFL module version in build time - Add a new tag for loader Change-Id: Ia450474d6f518670b603040cc3764616e47fe817 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 d129b47..15b0cc7 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.13.1 +Version: 0.14.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4