From c42584e660723713aa6896582b7dc37891f9c060 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 18 May 2020 12:38:26 +0900 Subject: [PATCH 01/16] Fix ASAN build issue Change-Id: Ife64bd725926ffac0b1cb4581b1b917ca3dd93bc Signed-off-by: Hwankyu Jhun --- src/hydra/src/launchpad_hydra.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/hydra/src/launchpad_hydra.c b/src/hydra/src/launchpad_hydra.c index f2c7779..3b94555 100644 --- a/src/hydra/src/launchpad_hydra.c +++ b/src/hydra/src/launchpad_hydra.c @@ -252,37 +252,35 @@ static int __handle_sigchld_event(sd_event_source *s, return 0; } -static int __create_client_socket(const char *path) +static int __create_client_socket(int type, int id) { struct sockaddr_un addr = { 0, }; int retry = CONNECT_RETRY_COUNT; int fd; - if (sizeof(addr.sun_path) <= strlen(path)) { - _E("lenght of path is too long"); - return -1; - } - fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (fd < 0) { - _E("Failed to create socket(%s). errno(%d)", path, errno); + _E("Failed to create socket(%d:%d). errno(%d)", + type, id, errno); return -1; } addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path)); - addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; + snprintf(addr.sun_path, sizeof(addr.sun_path), + "%s/daemons/%d/%s%d-%d", + SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, + type, id); while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (errno != ETIMEDOUT || retry <= 0) { _E("Failed to connect socket(%s). errno(%d)", - path, errno); + addr.sun_path, errno); close(fd); return -1; } usleep(CONNECT_RETRY_TIME); retry--; - _W("Retry(%d) to connect %s", retry, path); + _W("Retry(%d) to connect %s", retry, addr.sun_path); } return fd; @@ -290,7 +288,6 @@ static int __create_client_socket(const char *path) int __connect_to_launchpad_hydra(int type, int id) { - char path[PATH_MAX]; int fd; int send_ret; pid_t client_pid; @@ -298,10 +295,7 @@ int __connect_to_launchpad_hydra(int type, int id) _D("[hydra] enter, type: %d", type); - snprintf(path, sizeof(path), "%s/daemons/%d/%s%d-%d", - SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, - type, id); - fd = __create_client_socket(path); + fd = __create_client_socket(type, id); if (fd < 0) return -1; -- 2.7.4 From 6d04a1ac515e6efd3db6f0fcf91d4cdd56826730 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 18 May 2020 13:45:32 +0900 Subject: [PATCH 02/16] Release version 0.14.5 Changes: - Fix ASAN build issue Change-Id: Id141f6e85ed86de829437f5a83b678ee70589495 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 895aa65..e39fa09 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.14.4 +Version: 0.14.5 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From ce958985b913488dc10b14fd9f9ce9be1e12c596 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 19 May 2020 08:29:07 +0900 Subject: [PATCH 03/16] Change project name of launchpad library Change-Id: I20640bb7e230e823388548748ebbbe4279dc9798 Signed-off-by: Hwankyu Jhun --- src/CMakeLists.txt | 4 ++-- src/lib/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 352038e..de3c1c6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,5 +7,5 @@ ADD_SUBDIRECTORY(app-defined-loader) ADD_SUBDIRECTORY(hydra) ADD_SUBDIRECTORY(parser) -ADD_DEPENDENCIES(launchpad-loader launchpad-lib) -ADD_DEPENDENCIES(app-defined-loader launchpad-lib) +ADD_DEPENDENCIES(launchpad-loader liblaunchpad) +ADD_DEPENDENCIES(app-defined-loader liblaunchpad) diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index d5a2ecd..1d42ce0 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -1,5 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(launchpad-lib C) +PROJECT(liblaunchpad C) SET(LAUNCHPAD_LIB "launchpad") INCLUDE(FindPkgConfig) -- 2.7.4 From 3e9b00eb14490eb8ef40dd3942cf36555edca09c Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 18 May 2020 20:50:19 +0900 Subject: [PATCH 04/16] Fix loader management If the cpu check count has exceeded 10 times, the loader context is queuing and the next loader context will be checked. The platform developer can adjust the maximum CPU check count by modifying launchpad.conf file. Change-Id: I0e0917cff2b88cbf6d1a6ea2b0e2fedb983d9ebf Signed-off-by: Hwankyu Jhun --- src/launchpad/conf/launchpad.conf.in | 3 +++ src/launchpad/inc/launchpad_config.h | 1 + src/launchpad/src/launchpad.c | 30 ++++++++++++++++++++++++++---- src/launchpad/src/launchpad_config.c | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/launchpad/conf/launchpad.conf.in b/src/launchpad/conf/launchpad.conf.in index 3615188..6e7e6b2 100644 --- a/src/launchpad/conf/launchpad.conf.in +++ b/src/launchpad/conf/launchpad.conf.in @@ -7,3 +7,6 @@ NormalValue=1 [MemoryMonitor] Threshold=80 Interval=5000 + +[CpuChecker] +MaxCount=10 diff --git a/src/launchpad/inc/launchpad_config.h b/src/launchpad/inc/launchpad_config.h index 1d2ee1e..328f839 100644 --- a/src/launchpad/inc/launchpad_config.h +++ b/src/launchpad/inc/launchpad_config.h @@ -24,6 +24,7 @@ typedef enum { CONFIG_TYPE_MEMORY_STATUS_NORMAL_VALUE, CONFIG_TYPE_MEMORY_MONITOR_THRESHOLD, CONFIG_TYPE_MEMORY_MONITOR_INTERVAL, + CONFIG_TYPE_CPU_CHECKER_MAX_COUNT, } config_type_e; const char *_config_get_string_value(config_type_e type); diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index da7042b..de35efb 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -122,6 +122,7 @@ typedef struct { io_channel_h hydra_channel; unsigned int score; unsigned int pss; + int cpu_check_count; } candidate_process_context_t; typedef struct { @@ -167,6 +168,7 @@ static int __memory_status_normal; static sequencer __sequencer; static int MEMORY_STATUS_LOW; static int MEMORY_STATUS_NORMAL; +static int MAX_CPU_CHECK_COUNT; static io_channel_h __logger_channel; static io_channel_h __label_monitor_channel; @@ -231,6 +233,7 @@ static gboolean __handle_queuing_slots(gpointer data) _get_cpu_idle(&total, &idle); cpc->cpu_idle_time = idle; cpc->cpu_total_time = total; + cpc->cpu_check_count = 0; __sequencer.idle_checker = g_timeout_add(CPU_CHECKER_TIMEOUT, __handle_idle_checker, cpc); @@ -1603,14 +1606,16 @@ static gboolean __handle_idle_checker(gpointer data) cpc = (candidate_process_context_t *)data; if (cpc->app_check && !cpc->app_exists) { - _W("The application is not installed. Type(%d)", cpc->type); + _W("The application is not installed. loader(%s:%d)", + cpc->loader_name, cpc->type); __sequencer.idle_checker = 0; __sequencer.running_cpc = NULL; return G_SOURCE_REMOVE; } if (cpc->state != CANDIDATE_PROCESS_STATE_RUNNING) { - _W("Slot state is not running. Type(%d)", cpc->type); + _W("Slot state is not running. loader(%s:%d)", + cpc->loader_name, cpc->type); __sequencer.idle_checker = 0; __sequencer.running_cpc = NULL; return G_SOURCE_REMOVE; @@ -1621,7 +1626,7 @@ static gboolean __handle_idle_checker(gpointer data) total++; per = (idle - cpc->cpu_idle_time) * 100 / (total - cpc->cpu_total_time); - _D("[CPU] Idle : %d / type : %d", per, cpc->type); + _D("[CPU] Idle : %d / loader(%s:%d)", per, cpc->loader_name, cpc->type); if (per >= cpc->threshold) { __update_threshold(cpc, -0.02f * (per - cpc->threshold)); @@ -1636,6 +1641,18 @@ static gboolean __handle_idle_checker(gpointer data) cpc->cpu_total_time = total; __update_threshold(cpc, 0.05f); + cpc->cpu_check_count++; + if (cpc->cpu_check_count == MAX_CPU_CHECK_COUNT) { + _W("CPU check count has exceeded %d times. loader(%s:%d)", + cpc->cpu_check_count, + cpc->loader_name, + cpc->type); + __sequencer.idle_checker = 0; + __sequencer.running_cpc = NULL; + __sequencer_add_slot(cpc); + return G_SOURCE_REMOVE; + } + return G_SOURCE_CONTINUE; } @@ -2298,6 +2315,7 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, cpc->app_check = app_check; cpc->score = WIN_SCORE; cpc->pss = 0; + cpc->cpu_check_count = 0; if ((cpc->deactivation_method & METHOD_OUT_OF_MEMORY) && __is_low_memory()) @@ -2305,6 +2323,8 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, else cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; + _W("loader(%s), type(%d), state(%d)", + cpc->loader_name, cpc->type, cpc->state); return cpc; } @@ -2873,12 +2893,12 @@ 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; if (low_memory) { + _W("Low memory"); __update_slots_pss(); candidate_slot_list = g_list_sort(candidate_slot_list, @@ -2936,6 +2956,8 @@ static int __before_loop(int argc, char **argv) _inotify_init(); + MAX_CPU_CHECK_COUNT = _config_get_int_value( + CONFIG_TYPE_CPU_CHECKER_MAX_COUNT); __add_default_slots(); launcher_info_list = _launcher_info_load(LAUNCHER_INFO_PATH); diff --git a/src/launchpad/src/launchpad_config.c b/src/launchpad/src/launchpad_config.c index 5b517b0..0838dd7 100644 --- a/src/launchpad/src/launchpad_config.c +++ b/src/launchpad/src/launchpad_config.c @@ -40,6 +40,9 @@ #define KEY_MEMORY_MONITOR_THRESHOLD "Threshold" #define KEY_MEMORY_MONITOR_INTERVAL "Interval" +#define TAG_CPU_CHECKER "CpuChecker" +#define KEY_CPU_CHECKER_MAX_COUNT "MaxCount" + struct memory_status_s { char *low_key; int low_value; @@ -52,8 +55,13 @@ struct memory_monitor_s { int interval; }; +struct cpu_checker_s { + int max_count; +}; + static struct memory_status_s __memory_status; static struct memory_monitor_s __memory_monitor; +static struct cpu_checker_s __cpu_checker; const char *_config_get_string_value(config_type_e type) { @@ -92,6 +100,9 @@ int _config_get_int_value(config_type_e type) case CONFIG_TYPE_MEMORY_MONITOR_INTERVAL: value = __memory_monitor.interval; break; + case CONFIG_TYPE_CPU_CHECKER_MAX_COUNT: + value = __cpu_checker.max_count; + break; default: _E("Unknown type"); value = INT_MIN; @@ -208,6 +219,28 @@ static void __memory_monitor_set(dictionary *d) __memory_monitor.interval); } +static void __cpu_checker_init(void) +{ + __cpu_checker.max_count = 10; +} + +static void __cpu_checker_fini(void) +{ + __cpu_checker.max_count = 0; +} + +static void __cpu_checker_set(dictionary *d) +{ + int ret; + + ret = __get_int_value(d, TAG_CPU_CHECKER, + KEY_CPU_CHECKER_MAX_COUNT); + if (ret != INT_MAX) + __cpu_checker.max_count = ret; + + _W("CPU Checker MaxCount(%d)", __cpu_checker.max_count); +} + int _config_init(void) { dictionary *d; @@ -217,6 +250,7 @@ int _config_init(void) __memory_status_init(); __memory_monitor_init(); + __cpu_checker_init(); ret = access(PATH_LAUNCHPAD_CONF, F_OK); if (ret != 0) { @@ -232,6 +266,7 @@ int _config_init(void) __memory_status_set(d); __memory_monitor_set(d); + __cpu_checker_set(d); iniparser_freedict(d); @@ -242,6 +277,7 @@ void _config_fini(void) { _D("config fini"); + __cpu_checker_fini(); __memory_monitor_fini(); __memory_status_fini(); } -- 2.7.4 From 09cf7a499cc99a0e8065c28fd1338aa44ab58adf Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 18 May 2020 12:09:41 +0900 Subject: [PATCH 05/16] Support plugin module Before dropping capabilities of child process, the plugin module is called to prepare changing the application. Change-Id: I18600b383a3c7a87e8f0df012b7fda219bccbd6f Signed-off-by: Hwankyu Jhun --- src/common/inc/launchpad_plugin.h | 24 +++++++++++++++ src/common/src/launchpad_plugin.c | 61 +++++++++++++++++++++++++++++++++++++++ src/launchpad/CMakeLists.txt | 4 +-- src/launchpad/src/launchpad.c | 7 +++++ src/lib/src/launchpad_lib.c | 7 +++++ 5 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/common/inc/launchpad_plugin.h create mode 100644 src/common/src/launchpad_plugin.c diff --git a/src/common/inc/launchpad_plugin.h b/src/common/inc/launchpad_plugin.h new file mode 100644 index 0000000..f2cf987 --- /dev/null +++ b/src/common/inc/launchpad_plugin.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_PLUGIN_H__ +#define __LAUNCHPAD_PLUGIN_H__ + +#include + +int _launchpad_plugin_prepare_app(const char *app_id, bundle *kb); + +#endif /* __LAUNCHPAD_PLUGIN_H__ */ diff --git a/src/common/src/launchpad_plugin.c b/src/common/src/launchpad_plugin.c new file mode 100644 index 0000000..d54d4ec --- /dev/null +++ b/src/common/src/launchpad_plugin.c @@ -0,0 +1,61 @@ +/* + * 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_plugin.h" +#include "log_private.h" + +#define PATH_LAUNCHPAD_PLUGIN "/usr/share/aul/plugin/liblaunchpad-plugin.so" +#define TAG_LAUNCHPAD_PLUGIN_PREPARE_APP "LAUNCHPAD_PLUGIN_PREPARE_APP" + +int _launchpad_plugin_prepare_app(const char *app_id, bundle *kb) +{ + void *handle; + int (*prepare_app)(const char *, bundle *); + int ret; + + ret = access(PATH_LAUNCHPAD_PLUGIN, F_OK); + if (ret != 0) { + _D("plugin module does not exist. errno(%d)", errno); + return 0; + } + + handle = dlopen(PATH_LAUNCHPAD_PLUGIN, RTLD_LAZY | RTLD_LOCAL); + if (!handle) { + _W("Failed to open plugin so. error(%s)", dlerror()); + return 0; + } + + prepare_app = dlsym(handle, TAG_LAUNCHPAD_PLUGIN_PREPARE_APP); + if (!prepare_app) { + _W("Failed to load %s", TAG_LAUNCHPAD_PLUGIN_PREPARE_APP); + return 0; + } + + _W("LAUNCHPAD_PLUGIN_PREPARE_APP ++"); + ret = prepare_app(app_id, kb); + _W("LAUNCHPAD_PLUGIN_PREPARE_APP --"); + if (ret != 0) + return -1; + + return 0; +} diff --git a/src/launchpad/CMakeLists.txt b/src/launchpad/CMakeLists.txt index a51f395..39ce5c8 100644 --- a/src/launchpad/CMakeLists.txt +++ b/src/launchpad/CMakeLists.txt @@ -53,9 +53,9 @@ SET(LAUNCHPAD_PROCESS_POOL_SOURCE_FILES ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_SOURCE_FILES}) IF(_TIZEN_FEATURE_PRELINK) -TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_PKGS_LDFLAGS} "-lm") +TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_PKGS_LDFLAGS} "-lm -ldl") ELSE(_TIZEN_FEATURE_PRELINK) -TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_PKGS_LDFLAGS} "-pie -lm") +TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${LAUNCHPAD_PROCESS_POOL_PKGS_LDFLAGS} "-pie -lm -ldl") ENDIF(_TIZEN_FEATURE_PRELINK) SET_TARGET_PROPERTIES(${LAUNCHPAD_PROCESS_POOL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_pool}) diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index de35efb..9c7239d 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -47,6 +47,7 @@ #include "launchpad_inotify.h" #include "launchpad_io_channel.h" #include "launchpad_memory_monitor.h" +#include "launchpad_plugin.h" #include "launchpad_proc.h" #include "launchpad_signal.h" #include "launchpad_types.h" @@ -1211,6 +1212,12 @@ static int __prepare_exec(const char *appid, const char *app_path, /* TODO : should be add to check permission in the kernel*/ setsid(); + ret = _launchpad_plugin_prepare_app(appid, kb); + if (ret < 0) { + _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret); + return PAD_ERR_FAILED; + } + ret = _enable_external_pkg(kb, menu_info->pkgid, menu_info->global ? GLOBAL_USER : getuid()); if (ret < 0) diff --git a/src/lib/src/launchpad_lib.c b/src/lib/src/launchpad_lib.c index 45a59f9..d9d4434 100644 --- a/src/lib/src/launchpad_lib.c +++ b/src/lib/src/launchpad_lib.c @@ -35,6 +35,7 @@ #include "launchpad.h" #include "launchpad_common.h" +#include "launchpad_plugin.h" #include "launchpad_types.h" #include "preexec.h" @@ -71,6 +72,12 @@ static int __prepare_exec(const char *appid, const char *app_path, __preexec_run(pkg_type, appid, app_path); + ret = _launchpad_plugin_prepare_app(appid, kb); + if (ret != 0) { + _E("_launchpad_plugin_prepare_app() is failed. error(%d)", ret); + return -1; + } + ret = _enable_external_pkg(kb, pkgid, global ? GLOBAL_USER : getuid()); if (ret < 0) return -1; -- 2.7.4 From 71d30b08e6e735d3135173ea3ee69a96592b484c Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 19 May 2020 09:39:37 +0900 Subject: [PATCH 06/16] Fix resource leak Change-Id: If9de9ee89410b7cf27162be3d878d9035a30653b Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_plugin.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/src/launchpad_plugin.c b/src/common/src/launchpad_plugin.c index d54d4ec..912c19d 100644 --- a/src/common/src/launchpad_plugin.c +++ b/src/common/src/launchpad_plugin.c @@ -48,6 +48,7 @@ int _launchpad_plugin_prepare_app(const char *app_id, bundle *kb) prepare_app = dlsym(handle, TAG_LAUNCHPAD_PLUGIN_PREPARE_APP); if (!prepare_app) { _W("Failed to load %s", TAG_LAUNCHPAD_PLUGIN_PREPARE_APP); + dlclose(handle); return 0; } -- 2.7.4 From d1488f6d5ec4f7e86d6512323be1702dc3db7e66 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 19 May 2020 09:16:34 +0900 Subject: [PATCH 07/16] Release version 0.15.0 Changes: - Change project name of launchpad library - Fix loader management - Support plugin module - Fix resource leak Change-Id: I3245c3b75c6bc090c790809c5fd0f58826ffc0fb 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 e39fa09..9218b71 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.14.5 +Version: 0.15.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From e7a00d8d7119068198bf46b366ff9bd39ffd92b0 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 27 May 2020 20:13:15 +0900 Subject: [PATCH 08/16] Support ASAN debug mode Change-Id: I5ff27faf3ea93c478ff5fcb22845455787300dba Signed-off-by: Hwankyu Jhun --- packaging/default.debugger.in | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packaging/default.debugger.in b/packaging/default.debugger.in index b8e1651..90edf57 100644 --- a/packaging/default.debugger.in +++ b/packaging/default.debugger.in @@ -33,3 +33,10 @@ NAME GDB EXE /usr/bin/gdb APP_TYPE capp|c++app EXTRA_KEY __DLP_GDB_ARG__ + +[DEBUGGER] +NAME ASAN +APP_TYPE capp|c++app +EXTRA_ENV LD_PRELOAD +EXTRA_ENV ASAN_OPTIONS + -- 2.7.4 From e18746776e8bc13528057004218a457ee83b6e7e Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 29 May 2020 11:07:02 +0900 Subject: [PATCH 09/16] Set environment variables before executing the application To avoid thread-safe issue of setenv() / getenv(), the child process adds the environment variables to increase buffer size of __environ. Change-Id: Ia656b8c4cbc2fb5014a1fe399e78dfc9475dbf6d Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_common.c | 42 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index 26fce8b..8d2f943 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -40,6 +40,7 @@ #include #include #include +#include #include "launchpad_common.h" #include "launchpad_types.h" @@ -726,6 +727,44 @@ static void __set_execution_domain(void) } #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */ +static void __set_lang_env(void) +{ + char *lang; + + lang = vconf_get_str(VCONFKEY_LANGSET); + if (!lang) + lang = strdup("en_US.UTF-8"); + + setenv("LANGUAGE", lang, 1); + setenv("LANG", lang, 1); + setenv("LC_MESSAGES", lang, 1); + + free(lang); +} + +static void __set_region_env(void) +{ + char *region; + + region = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (!region) + region = strdup("en_US.UTF-8"); + + setenv("LC_CTYPE", region, 1); + setenv("LC_NUMERIC", region, 1); + setenv("LC_TIME", region, 1); + setenv("LC_COLLATE", region, 1); + setenv("LC_MONETARY", region, 1); + setenv("LC_PAPER", region, 1); + setenv("LC_NAME", region, 1); + setenv("LC_ADDRESS", region, 1); + setenv("LC_TELEPHONE", region, 1); + setenv("LC_MEASUREMENT", region, 1); + setenv("LC_IDENTIFICATION", region, 1); + + free(region); +} + void _set_env(appinfo_t *menu_info, bundle *kb) { const char *str; @@ -763,6 +802,9 @@ void _set_env(appinfo_t *menu_info, bundle *kb) snprintf(buf, sizeof(buf), "%d", getpid()); setenv("AUL_PID", buf, 1); + __set_lang_env(); + __set_region_env(); + setenv("LC_ALL", "C", 1); #ifdef TIZEN_FEATURE_SET_PERSONALITY_32 __set_execution_domain(); #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */ -- 2.7.4 From 526cd30c05737e583a70cf4a66c3a8016245c297 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 29 May 2020 11:27:37 +0900 Subject: [PATCH 10/16] Release version 0.15.1 Changes: - Support ASAN debug mode - Set environment variables before executing the application Change-Id: Id6beb8ce372038a015e040cf5f0319bf7e71c4b3 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 9218b71..2d66809 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.15.0 +Version: 0.15.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 676c0c7a274270012a17a5ecf4bc073b50e3f697 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 1 Jun 2020 09:15:28 +0900 Subject: [PATCH 11/16] Remove getting vconf values This patch removes getting vconf values while launching an application. Sometimes, calling vconf API in the child process is failed by timed out error. If the environment variable is already set, the child process uses it to set. If it's not, the child process uses "en_US.UTF-8". Change-Id: I8b630a3c3874d00bd3120fb0f2c7e689d3574818 Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_common.c | 26 ++++++++++++-------------- src/launchpad/src/launchpad.c | 38 +++++++++++++++++++++++++++++++++++--- src/lib/src/launchpad_lib.c | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index 8d2f943..281a6fc 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -729,28 +729,28 @@ static void __set_execution_domain(void) static void __set_lang_env(void) { - char *lang; + const char *lang; - lang = vconf_get_str(VCONFKEY_LANGSET); - if (!lang) - lang = strdup("en_US.UTF-8"); + lang = getenv("LANG"); + if (!lang) { + lang = "en_US.UTF-8"; + setenv("LANG", lang, 1); + } setenv("LANGUAGE", lang, 1); - setenv("LANG", lang, 1); setenv("LC_MESSAGES", lang, 1); - - free(lang); } static void __set_region_env(void) { - char *region; + const char *region; - region = vconf_get_str(VCONFKEY_REGIONFORMAT); - if (!region) - region = strdup("en_US.UTF-8"); + region = getenv("LC_CTYPE"); + if (!region) { + region = "en_US.UTF-8"; + setenv("LC_CTYPE", region, 1); + } - setenv("LC_CTYPE", region, 1); setenv("LC_NUMERIC", region, 1); setenv("LC_TIME", region, 1); setenv("LC_COLLATE", region, 1); @@ -761,8 +761,6 @@ static void __set_region_env(void) setenv("LC_TELEPHONE", region, 1); setenv("LC_MEASUREMENT", region, 1); setenv("LC_IDENTIFICATION", region, 1); - - free(region); } void _set_env(appinfo_t *menu_info, bundle *kb) diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 9c7239d..217be80 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -2727,10 +2727,28 @@ static void __hw_acceleration_changed_cb(keynode_t *key, void *data) static void __update_lang(keynode_t *node, void *user_data) { - char *lang = vconf_keynode_get_str(node); + char *lang; - if (lang) - setenv("LANG", lang, 1); + lang = vconf_keynode_get_str(node); + if (!lang) { + _E("Failed to get language"); + return; + } + + setenv("LANG", lang, 1); +} + +static void __region_format_changed_cb(keynode_t *node, void *data) +{ + char *region; + + region = vconf_keynode_get_str(node); + if (!region) { + _E("Failed to get value"); + return; + } + + setenv("LC_CTYPE", region, 1); } static void __memory_status_low_changed_cb(keynode_t *node, void *data) @@ -2780,6 +2798,8 @@ static void __unregister_vconf_events(void) key = _config_get_string_value(type); vconf_ignore_key_changed(key, __memory_status_low_changed_cb); + vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, + __region_format_changed_cb); vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang); vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, @@ -2790,6 +2810,7 @@ static int __register_vconf_events(void) { int r; char *lang; + char *region; const char *key; config_type_e type; @@ -2814,6 +2835,17 @@ static int __register_vconf_events(void) if (r != VCONF_OK) _E("Failed to register callback for langset. err = %d", r); + region = vconf_get_str(VCONFKEY_REGIONFORMAT); + if (region) { + setenv("LC_CTYPE", region, 1); + free(region); + } + + r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, + __region_format_changed_cb, NULL); + if (r != VCONF_OK) + _E("Failed to register callback for regionformat. err = %d", r); + type = CONFIG_TYPE_MEMORY_STATUS_LOW_KEY; key = _config_get_string_value(type); type = CONFIG_TYPE_MEMORY_STATUS_LOW_VALUE; diff --git a/src/lib/src/launchpad_lib.c b/src/lib/src/launchpad_lib.c index d9d4434..9852ecd 100644 --- a/src/lib/src/launchpad_lib.c +++ b/src/lib/src/launchpad_lib.c @@ -321,10 +321,28 @@ static void __receiver_cb(int fd) static void __update_lang(keynode_t *node, void *user_data) { - char *lang = vconf_keynode_get_str(node); + char *lang; - if (lang) - setenv("LANG", lang, 1); + lang = vconf_keynode_get_str(node); + if (!lang) { + _E("Failed to get language"); + return; + } + + setenv("LANG", lang, 1); +} + +static void __region_format_changed_cb(keynode_t *node, void *user_data) +{ + char *region; + + region = vconf_keynode_get_str(node); + if (!region) { + _E("Failed to get regionformat"); + return; + } + + setenv("LC_CTYPE", region, 1); } static int __before_loop(int argc, char **argv) @@ -332,6 +350,7 @@ static int __before_loop(int argc, char **argv) int client_fd; int ret = -1; bundle *extra = NULL; + int r; if (_verify_proc_caps() < 0) return -1; @@ -371,14 +390,22 @@ static int __before_loop(int argc, char **argv) __loader_adapter->add_fd(__loader_user_data, client_fd, __receiver_cb); - if (vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL) != 0) - _E("vconf_notify_key_changed failed"); + r = vconf_notify_key_changed(VCONFKEY_LANGSET, __update_lang, NULL); + if (r != VCONF_OK) + _E("Failed to register callback for langset. error(%d)", r); + + r = vconf_notify_key_changed(VCONFKEY_REGIONFORMAT, + __region_format_changed_cb, NULL); + if (r != VCONF_OK) + _E("Failed to register callback for regionformat. error(%d)", r); return ret; } static int __after_loop(void) { + vconf_ignore_key_changed(VCONFKEY_REGIONFORMAT, + __region_format_changed_cb); vconf_ignore_key_changed(VCONFKEY_LANGSET, __update_lang); if (__loader_callbacks->terminate) { -- 2.7.4 From 509943299ba695c03146473997d818f6c05c0fdd Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 1 Jun 2020 09:34:13 +0900 Subject: [PATCH 12/16] Release version 0.15.2 Changes: - Remove getting vconf values Change-Id: Ia5f07f8b63337fbecd989461d57649b85982ef3e 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 2d66809..7f2693a 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.15.1 +Version: 0.15.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From cfd12b82526ba28ed624b66305f73cc9f52ddd3e Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 1 Jun 2020 10:22:06 +0900 Subject: [PATCH 13/16] Add logs for debugging launching performance Change-Id: Ide2343c0b9e2aebcbc1c4d75e2c04584008f960e Signed-off-by: Hwankyu Jhun --- src/app-defined-loader/src/app-defined-loader.cc | 3 ++- src/loader/src/launchpad_loader.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/app-defined-loader/src/app-defined-loader.cc b/src/app-defined-loader/src/app-defined-loader.cc index 38ffb94..7cc0a88 100644 --- a/src/app-defined-loader/src/app-defined-loader.cc +++ b/src/app-defined-loader/src/app-defined-loader.cc @@ -207,12 +207,13 @@ class AppDefinedLoader { } int DoDlOpen(bool restore, std::string old_cwd, std::string libdir) { - _I("do dlopen"); std::string hwc_message = "" + std::to_string(getpid()) + "|lib loading start"; prctl(PR_TASK_PERF_USER_TRACE, hwc_message.c_str(), hwc_message.size()); + _W("dlopen(%s) ++", argv_[LOADER_ARG_PATH]); void* handle = dlopen(argv_[LOADER_ARG_PATH], RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE); + _W("dlopen(%s) --", argv_[LOADER_ARG_PATH]); if (handle == nullptr) { _E("dlopen(%s) is failed. error(%s)", argv_[LOADER_ARG_PATH], dlerror()); DoExec(libdir); diff --git a/src/loader/src/launchpad_loader.c b/src/loader/src/launchpad_loader.c index b67484d..fbe0b76 100644 --- a/src/loader/src/launchpad_loader.c +++ b/src/loader/src/launchpad_loader.c @@ -344,8 +344,10 @@ static int __loader_terminate_cb(int argc, char **argv, void *user_data) do_dlopen: snprintf(hwc_message, sizeof(hwc_message), "%d|lib loading start", getpid()); prctl(PR_TASK_PERF_USER_TRACE, hwc_message, strlen(hwc_message)); + _W("dlopen(%s) ++", argv[LOADER_ARG_PATH]); handle = dlopen(argv[LOADER_ARG_PATH], RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE); + _W("dlopen(%s) --", argv[LOADER_ARG_PATH]); if (handle == NULL) { _E("dlopen(%s) is failed. error(%s)", argv[LOADER_ARG_PATH], dlerror()); -- 2.7.4 From 3a6ce5337fecef0749144ea9d83adfbcb2a0d75b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 2 Jun 2020 16:32:49 +0900 Subject: [PATCH 14/16] Release version 0.15.3 Changes: - Add logs for debugging launching performance Change-Id: I7a033eabe7046a5d46499e34427e527033f7aa78 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 7f2693a..736ef9b 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.15.2 +Version: 0.15.3 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From ef2ba5f7f60109843703489d1a4ef348af976437 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 12 Jun 2020 10:25:22 +0900 Subject: [PATCH 15/16] Fix setting LC_ALL env Change-Id: Ifb0e2fc6da3a425fafdb771b900d270b540ba0bb Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index 281a6fc..815bb30 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -739,6 +739,7 @@ static void __set_lang_env(void) setenv("LANGUAGE", lang, 1); setenv("LC_MESSAGES", lang, 1); + setenv("LC_ALL", lang, 1); } static void __set_region_env(void) @@ -802,7 +803,6 @@ void _set_env(appinfo_t *menu_info, bundle *kb) __set_lang_env(); __set_region_env(); - setenv("LC_ALL", "C", 1); #ifdef TIZEN_FEATURE_SET_PERSONALITY_32 __set_execution_domain(); #endif /* TIZEN_FEATURE_SET_PERSONALITY_32 */ -- 2.7.4 From b23152f7aa83375ea7a6f75de973af700097dc54 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 9 Jun 2020 20:53:46 +0900 Subject: [PATCH 16/16] Fix hydra sigchld handler When the child process of the hydra loader is dead, the hydra loader sends the signal to the launchpad-process-pool. This patch separates launchpad_signal.c file. Change-Id: Idaddf9c963b331e1257fbeb8d8f1f985adbd9b0a Signed-off-by: Hwankyu Jhun --- src/common/inc/launchpad_common.h | 1 - src/common/inc/launchpad_proc.h | 10 + src/common/inc/launchpad_socket.h | 52 ++++ src/common/src/launchpad_common.c | 37 --- src/common/src/launchpad_proc.c | 47 ++++ src/common/src/launchpad_socket.c | 407 +++++++++++++++++++++++++++ src/hydra/CMakeLists.txt | 6 +- src/hydra/inc/launchpad_sigchld.h | 30 ++ src/hydra/src/launchpad_hydra.c | 7 +- src/hydra/src/launchpad_sigchld.c | 50 ++++ src/launchpad/inc/launchpad_dbus.h | 36 +++ src/launchpad/inc/launchpad_io_channel.h | 2 + src/launchpad/inc/launchpad_signal.h | 25 +- src/launchpad/src/launchpad.c | 109 +++---- src/launchpad/src/launchpad_dbus.c | 278 ++++++++++++++++++ src/launchpad/src/launchpad_io_channel.c | 19 +- src/launchpad/src/launchpad_signal.c | 469 ++++++++++++++----------------- 17 files changed, 1201 insertions(+), 384 deletions(-) create mode 100644 src/common/inc/launchpad_socket.h create mode 100644 src/common/src/launchpad_socket.c create mode 100644 src/hydra/inc/launchpad_sigchld.h create mode 100644 src/hydra/src/launchpad_sigchld.c create mode 100644 src/launchpad/inc/launchpad_dbus.h create mode 100644 src/launchpad/src/launchpad_dbus.c diff --git a/src/common/inc/launchpad_common.h b/src/common/inc/launchpad_common.h index 5d97b77..0850aed 100644 --- a/src/common/inc/launchpad_common.h +++ b/src/common/inc/launchpad_common.h @@ -124,7 +124,6 @@ int _delete_sock_path(int pid, uid_t uid); appinfo_t *_appinfo_create(bundle *kb); void _appinfo_free(appinfo_t *menu_info); char *_appinfo_get_app_path(appinfo_t *menu_info); -int _proc_get_attr_by_pid(int pid, char *buf, int size); int _close_all_fds(void); void _get_cpu_idle(unsigned long long *total, unsigned long long *idle); int _setup_stdio(const char *ident); diff --git a/src/common/inc/launchpad_proc.h b/src/common/inc/launchpad_proc.h index eaff0f6..fe2b9ad 100644 --- a/src/common/inc/launchpad_proc.h +++ b/src/common/inc/launchpad_proc.h @@ -17,8 +17,18 @@ #ifndef __LAUNCHPAD_PROC_H__ #define __LAUNCHPAD_PROC_H__ +#ifdef __cplusplus +extern "C" { +#endif + int _proc_get_mem_used_ratio(unsigned int *mem_used_ratio); int _proc_get_mem_pss(int pid, unsigned int *mem_pss); +int _proc_get_attr(int pid, void *buf, unsigned int size); + +#ifdef __cplusplus +} +#endif + #endif /* __LAUNCHPAD_PROC_H__ */ diff --git a/src/common/inc/launchpad_socket.h b/src/common/inc/launchpad_socket.h new file mode 100644 index 0000000..b90de31 --- /dev/null +++ b/src/common/inc/launchpad_socket.h @@ -0,0 +1,52 @@ +/* + * 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_SOCKET_H__ +#define __LAUNCHPAD_SOCKET_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define LAUNCHPAD_SOCKET_PATH_SIZE 108 + +typedef struct socket_s *socket_h; + +int _socket_create(const char *path, bool client, socket_h *handle); + +int _socket_create_with_fd(int fd, socket_h *handle); + +int _socket_destroy(socket_h handle); + +int _socket_accept(socket_h handle, socket_h *client_socket); + +int _socket_get_fd(socket_h handle, int *fd); + +int _socket_set_fd(socket_h handle, int fd); + +int _socket_get_pid(socket_h handle, int *pid); + +int _socket_send(socket_h handle, const void *buf, unsigned int size); + +int _socket_read(socket_h handle, void *buf, unsigned int size); + +#ifdef __cplusplus +} +#endif + +#endif /* __LAUNCHPAD_SOCKET_H__ */ diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index 815bb30..e41a391 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -72,30 +72,6 @@ #define PR_TASK_PERF_USER_TRACE 666 #endif -static int __read_proc(const char *path, char *buf, int size) -{ - int fd; - int ret; - - if (buf == NULL || path == NULL) - return -1; - - fd = open(path, O_RDONLY); - if (fd < 0) - return -1; - - ret = read(fd, buf, size - 1); - if (ret <= 0) { - close(fd); - return -1; - } - - buf[ret] = 0; - close(fd); - - return ret; -} - void _get_cpu_idle(unsigned long long *total, unsigned long long *idle) { FILE *fp; @@ -847,19 +823,6 @@ char *_get_libdir(const char *path) return strdup(buf); } -int _proc_get_attr_by_pid(int pid, char *buf, int size) -{ - char path[PATH_MAX] = { 0, }; - int ret; - - snprintf(path, sizeof(path), "/proc/%d/attr/current", pid); - ret = __read_proc(path, buf, size); - if (ret <= 0) - return -1; - - return 0; -} - static int __delete_dir(const char *path) { DIR *dp; diff --git a/src/common/src/launchpad_proc.c b/src/common/src/launchpad_proc.c index e491cff..e390b2b 100644 --- a/src/common/src/launchpad_proc.c +++ b/src/common/src/launchpad_proc.c @@ -16,11 +16,15 @@ #define _GNU_SOURCE #include +#include #include #include #include #include #include +#include +#include +#include #include "launchpad_proc.h" #include "log_private.h" @@ -143,3 +147,46 @@ int _proc_get_mem_pss(int pid, unsigned int *mem_pss) return 0; } + +static void __close_fd(int *fd) +{ + if (!fd) + return; + + if (*fd < 0) + return; + + close(*fd); +} + +int _proc_get_attr(int pid, void *buf, unsigned int size) +{ + auto_ptr(__close_fd) int fd = -1; + char path[PATH_MAX]; + char *buffer = buf; + int ret; + + if (pid < 1 || !buf || !size) { + _E("Invalid parameter"); + return -EINVAL; + } + + snprintf(path, sizeof(path), "/proc/%d/attr/current", pid); + fd = open(path, O_RDONLY); + if (fd < 0) { + ret = -errno; + _E("open() is failed. errno(%d)", errno); + return ret; + } + + ret = read(fd, buffer, size - 1); + if (ret < 0) { + ret = -errno; + _E("read() is failed. fd(%d), errno(%d)", fd, errno); + return ret; + } + + buffer[ret] = 0; + + return 0; +} diff --git a/src/common/src/launchpad_socket.c b/src/common/src/launchpad_socket.c new file mode 100644 index 0000000..a79905b --- /dev/null +++ b/src/common/src/launchpad_socket.c @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "launchpad_socket.h" +#include "log_private.h" + +#define LAUNCHPAD_SOCKET_MAX_BUFF 131071 +#define LAUNCHPAD_SOCKET_RETRY_TIME (100 * 1000) +#define LAUNCHPAD_SOCKET_RETRY_COUNT 3 +#define LAUNCHPAD_SOCKET_MAX_PENDING_CONNECTION 128 + +struct socket_s { + char *path; + bool client; + int fd; + int pid; +}; + +static int __set_socket_option(int fd, bool client) +{ + struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */ + int size = LAUNCHPAD_SOCKET_MAX_BUFF; + int flag; + int ret; + + ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); + if (ret < 0) { + ret = -errno; + _E("setsockopt(SO_SNDBUF) is failed. fd(%d), errno(%d)", + fd, errno); + return ret; + } + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); + if (ret < 0) { + ret = -errno; + _E("setsockopt(SO_RCVBUF) is failed. fd(%d), errno(%d)", + fd, errno); + return ret; + } + + if (!client) + return 0; + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + if (ret < 0) { + ret = -errno; + _E("setsockopt(SO_RCVTIMEO) is failed. fd(%d), errno(%d)", + fd, errno); + return ret; + } + + flag = fcntl(fd, F_GETFD); + flag |= FD_CLOEXEC; + ret = fcntl(fd, F_SETFD, flag); + if (ret < 0) { + ret = -errno; + _E("fcntl(F_SETFD) is failed. fd(%d), errno(%d)", fd, errno); + return ret; + } + + return 0; +} + +static int __create_server_socket(const char *path) +{ + struct sockaddr_un addr = { 0, }; + int ret; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + ret = -errno; + _E("socket() is failed. path(%s), errno(%d)", path, errno); + return ret; + } + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); + unlink(addr.sun_path); + + ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); + if (ret < 0) { + ret = -errno; + _E("bind() is failed. path(%s), errno(%d)", path, errno); + close(fd); + return ret; + } + + ret = __set_socket_option(fd, false); + if (ret < 0) { + close(fd); + return ret; + } + + ret = listen(fd, LAUNCHPAD_SOCKET_MAX_PENDING_CONNECTION); + if (ret < 0) { + ret = -errno; + _E("listen() is failed. path(%s), errno(%d)", path, errno); + close(fd); + return ret; + } + + return fd; +} + +static int __create_client_socket(const char *path) +{ + struct sockaddr_un addr = { 0, }; + int retry = LAUNCHPAD_SOCKET_RETRY_COUNT; + int ret; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + ret = -errno; + _E("socket() is failed. path(%s), errno(%d)", path, errno); + return ret; + } + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); + while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (errno != ETIMEDOUT || retry <= 0) { + ret = -errno; + _E("connect() is failed. path(%s), errno(%d)", + path, errno); + close(fd); + return ret; + } + + usleep(LAUNCHPAD_SOCKET_RETRY_TIME); + retry--; + _W("Retry(%d) to connect to %s", retry, path); + } + + ret = __set_socket_option(fd, true); + if (ret < 0) { + close(fd); + return ret; + } + + return fd; +} + +static void __destroy_socket(struct socket_s *sock) +{ + if (!sock) + return; + + if (!sock->client && sock->fd > 0 && sock->path) + unlink(sock->path); + + free(sock->path); + free(sock); +} + +static struct socket_s *__create_socket(const char *path, bool client, + int fd, int pid) +{ + struct socket_s *sock; + + sock = calloc(1, sizeof(struct socket_s)); + if (!sock) { + _E("Out of memory"); + return NULL; + } + + if (path) { + sock->path = strdup(path); + if (!sock->path) { + _E("Failed to duplicate socket path(%s)", path); + __destroy_socket(sock); + return NULL; + } + } + + sock->client = client; + sock->fd = fd; + sock->pid = pid; + + return sock; +} + +int _socket_create(const char *path, bool client, socket_h *handle) +{ + struct socket_s *sock; + int fd; + + if (!path || !handle) { + _E("Invalid parameter"); + return -EINVAL; + } + + if (client) + fd = __create_client_socket(path); + else + fd = __create_server_socket(path); + + if (fd < 0) + return fd; + + sock = __create_socket(path, client, fd, getpid()); + if (!sock) { + close(fd); + return -ENOMEM; + } + + *handle = sock; + + return 0; +} + +int _socket_create_with_fd(int fd, socket_h *handle) +{ + struct socket_s *sock; + + if (fd < 0 || !handle) { + _E("Invalid parameter"); + return -EINVAL; + } + + sock = __create_socket(NULL, true, fd, getpid()); + if (!sock) + return -ENOMEM; + + *handle = sock; + + return 0; +} + +int _socket_destroy(socket_h handle) +{ + if (!handle) { + _E("Invalid parameter"); + return -EINVAL; + } + + if (handle->fd > 0) + close(handle->fd); + + __destroy_socket(handle); + + return 0; +} + +int _socket_accept(socket_h handle, socket_h *client_socket) +{ + struct socket_s *sock; + struct sockaddr_un addr = { 0, }; + struct ucred cred = { 0, }; + socklen_t addr_size = sizeof(struct sockaddr_un); + socklen_t cred_size = sizeof(struct ucred); + int client_fd; + int ret; + + if (!handle || !client_socket) { + _E("Invalid parameter"); + return -EINVAL; + } + + client_fd = accept(handle->fd, (struct sockaddr *)&addr, &addr_size); + if (client_fd < 0) { + ret = -errno; + _E("accept() is failed. errno(%d)", errno); + return ret; + } + + ret = getsockopt(client_fd, SOL_SOCKET, SO_PEERCRED, &cred, &cred_size); + if (ret < 0) { + ret = -errno; + _E("getsockopt(SO_PEERCRED) is failed. errno(%d)", errno); + close(client_fd); + return ret; + } + + ret = __set_socket_option(client_fd, true); + if (ret < 0) { + close(client_fd); + return ret; + } + + sock = __create_socket(NULL, true, client_fd, cred.pid); + if (!sock) { + close(client_fd); + return -ENOMEM; + } + + *client_socket = sock; + + return 0; +} + +int _socket_get_fd(socket_h handle, int *fd) +{ + if (!handle || !fd) { + _E("Invalid parameter"); + return -EINVAL; + } + + *fd = handle->fd; + + return 0; +} + +int _socket_set_fd(socket_h handle, int fd) +{ + if (!handle) { + _E("Invalid parameter"); + return -EINVAL; + } + + handle->fd = fd; + + return 0; +} + +int _socket_get_pid(socket_h handle, int *pid) +{ + if (!handle || !pid) { + _E("Invalid parameter"); + return -EINVAL; + } + + *pid = handle->pid; + + return 0; +} + +int _socket_send(socket_h handle, const void *buf, unsigned int size) +{ + unsigned char *buffer = (unsigned char *)buf; + unsigned int left = size; + ssize_t write_size; + int ret; + + if (!handle || !buf || !size) { + _E("Invalid parameter"); + return -EINVAL; + } + + while (left) { + write_size = send(handle->fd, buffer, left, MSG_NOSIGNAL); + if (write_size < 0) { + ret = -errno; + _E("send() is failed. fd(%d), errno(%d)", + handle->fd, errno); + return ret; + } + + left -= write_size; + buffer += write_size; + } + + return 0; +} + +int _socket_read(socket_h handle, void *buf, unsigned int size) +{ + unsigned char *buffer = (unsigned char *)buf; + unsigned int left = size; + ssize_t read_size; + + if (!handle || !buf || !size) { + _E("Invalid parameter"); + return -EINVAL; + } + + while (left) { + read_size = read(handle->fd, buffer, left); + if (read_size == 0) { + _W("EOF. fd(%d)", handle->fd); + return -EIO; + } else if (read_size < 0) { + return -errno; + } + + left -= read_size; + buffer += read_size; + } + + return 0; +} diff --git a/src/hydra/CMakeLists.txt b/src/hydra/CMakeLists.txt index 0ff9ebe..6aeab28 100644 --- a/src/hydra/CMakeLists.txt +++ b/src/hydra/CMakeLists.txt @@ -27,8 +27,12 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/inc) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src/common/inc) AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCES) +SET(COMMON_SOURCES + ${CMAKE_SOURCE_DIR}/src/common/src/launchpad_socket.c) -ADD_LIBRARY(${LAUNCHPAD_HYDRA} SHARED ${SOURCES}) +ADD_LIBRARY(${LAUNCHPAD_HYDRA} SHARED + ${SOURCES} + ${COMMON_SOURCES}) SET_TARGET_PROPERTIES(${LAUNCHPAD_HYDRA} PROPERTIES SOVERSION ${MAJORVER}) SET_TARGET_PROPERTIES(${LAUNCHPAD_HYDRA} PROPERTIES VERSION ${VERSION}) SET_TARGET_PROPERTIES(${LAUNCHPAD_HYDRA} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_hydra}) diff --git a/src/hydra/inc/launchpad_sigchld.h b/src/hydra/inc/launchpad_sigchld.h new file mode 100644 index 0000000..bd4b968 --- /dev/null +++ b/src/hydra/inc/launchpad_sigchld.h @@ -0,0 +1,30 @@ +/* + * 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_SIGCHLD_H__ +#define __LAUNCHPAD_SIGCHLD_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int _sigchld_send(int pid); + +#ifdef __cplusplus +} +#endif + +#endif /* __LAUNCHPAD_SIGCHLD_H__ */ diff --git a/src/hydra/src/launchpad_hydra.c b/src/hydra/src/launchpad_hydra.c index 3b94555..aa737fd 100644 --- a/src/hydra/src/launchpad_hydra.c +++ b/src/hydra/src/launchpad_hydra.c @@ -32,6 +32,7 @@ #include #include "launchpad_hydra.h" +#include "launchpad_sigchld.h" #include "launchpad_types.h" #include "log_private.h" @@ -211,13 +212,12 @@ err: static int __process_sigchld(struct signalfd_siginfo *info) { - union sigval val; int status; pid_t child_pid; pid_t child_pgid; child_pgid = getpgid(info->ssi_pid); - _D("[__HYDRA__] Dead pid(%d), pgid(%d), signo(%d), status(%d)", + _W("[__HYDRA__] Dead pid(%d), pgid(%d), signo(%d), status(%d)", info->ssi_pid, child_pgid, info->ssi_signo, info->ssi_status); @@ -225,8 +225,7 @@ static int __process_sigchld(struct signalfd_siginfo *info) if (child_pid == child_pgid) killpg(child_pgid, SIGKILL); - val.sival_int = child_pid; - sigqueue(getppid(), SIGCHLD, val); + _sigchld_send(child_pid); } return 0; diff --git a/src/hydra/src/launchpad_sigchld.c b/src/hydra/src/launchpad_sigchld.c new file mode 100644 index 0000000..487cf99 --- /dev/null +++ b/src/hydra/src/launchpad_sigchld.c @@ -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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include + +#include "launchpad_sigchld.h" +#include "launchpad_socket.h" +#include "log_private.h" + +#define HYDRA_SIGCHLD_SOCK ".hydra-sigchld-sock" + +int _sigchld_send(int pid) +{ + socket_h sock; + char path[LAUNCHPAD_SOCKET_PATH_SIZE]; + int ret; + + if (pid <= 1) { + _E("Invalid parameter"); + return -EINVAL; + } + + snprintf(path, sizeof(path), "/run/aul/daemons/%u/%s", + getuid(), HYDRA_SIGCHLD_SOCK); + ret = _socket_create(path, true, &sock); + if (ret < 0) + return ret; + + ret = _socket_send(sock, &pid, sizeof(pid)); + _socket_destroy(sock); + + return ret; +} diff --git a/src/launchpad/inc/launchpad_dbus.h b/src/launchpad/inc/launchpad_dbus.h new file mode 100644 index 0000000..685d89a --- /dev/null +++ b/src/launchpad/inc/launchpad_dbus.h @@ -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. + */ + +#ifndef __LAUNCHPAD_DBUS_H__ +#define __LAUNCHPAD_DBUS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +int _dbus_send_app_launch_signal(int pid, const char *app_id); + +int _dbus_send_app_dead_signal(int pid); + +int _dbus_init(void); + +void _dbus_fini(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LAUNCHPAD_DBUS_H__ */ diff --git a/src/launchpad/inc/launchpad_io_channel.h b/src/launchpad/inc/launchpad_io_channel.h index 6498fb3..b9ae867 100644 --- a/src/launchpad/inc/launchpad_io_channel.h +++ b/src/launchpad/inc/launchpad_io_channel.h @@ -36,3 +36,5 @@ io_channel_h _io_channel_create(int fd, io_condition_e condition, io_channel_event_cb, void *user_data); void _io_channel_destroy(io_channel_h channel); + +int _io_channel_set_close_on_destroy(io_channel_h channel, bool do_close); diff --git a/src/launchpad/inc/launchpad_signal.h b/src/launchpad/inc/launchpad_signal.h index a2dbccb..aea5654 100644 --- a/src/launchpad/inc/launchpad_signal.h +++ b/src/launchpad/inc/launchpad_signal.h @@ -1,14 +1,14 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016 - 2020 Samsung Electronics Co., Ltd All Rights Reserved * - * Licensed under the Apache License, Version 2.0 (the License); + * 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, + * 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. @@ -17,15 +17,20 @@ #ifndef __LAUNCHPAD_SIGNAL_H__ #define __LAUNCHPAD_SIGNAL_H__ -#include -#include -#include +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*signal_sigchld_cb)(int pid, void *user_data); + +int _signal_set_sigchld_cb(signal_sigchld_cb callback, void *user_data); -int _signal_send_app_launch_signal(int launch_pid, const char *app_id); -void _signal_process_sigchld(struct signalfd_siginfo *info); -int _signal_get_sigchld_fd(void); -int _signal_unblock_sigchld(void); int _signal_init(void); + void _signal_fini(void); +#ifdef __cplusplus +} +#endif + #endif /* __LAUNCHPAD_SIGNAL_H__ */ diff --git a/src/launchpad/src/launchpad.c b/src/launchpad/src/launchpad.c index 217be80..02aab1b 100644 --- a/src/launchpad/src/launchpad.c +++ b/src/launchpad/src/launchpad.c @@ -43,6 +43,7 @@ #include "launcher_info.h" #include "launchpad_common.h" #include "launchpad_config.h" +#include "launchpad_dbus.h" #include "launchpad_debug.h" #include "launchpad_inotify.h" #include "launchpad_io_channel.h" @@ -173,7 +174,6 @@ static int MAX_CPU_CHECK_COUNT; static io_channel_h __logger_channel; static io_channel_h __label_monitor_channel; -static io_channel_h __sigchild_channel; static io_channel_h __launchpad_channel; static candidate_process_context_t *__add_slot(int type, int loader_id, @@ -781,7 +781,7 @@ static int __exec_loader_process(void *arg) char err_buf[1024]; _send_cmd_to_amd(LAUNCHPAD_CHILD_PROCESS); - _signal_unblock_sigchld(); + _signal_fini(); _close_all_fds(); _setup_stdio(basename(argv[LOADER_ARG_PATH])); @@ -1296,7 +1296,7 @@ static int __exec_app_process(void *arg) if (bundle_get_type(launch_arg->kb, AUL_K_SDK) != BUNDLE_TYPE_NONE) _debug_prepare_debugger(launch_arg->kb); - _signal_unblock_sigchld(); + _signal_fini(); _delete_sock_path(getpid(), getuid()); @@ -1354,9 +1354,6 @@ static int __launchpad_pre_init(int argc, char **argv) { int fd; - /* signal init*/ - _signal_init(); - /* create launchpad sock */ fd = __create_sock_activation(); if (fd < 0) { @@ -1483,56 +1480,36 @@ static bool __handle_hydra_event(int fd, io_condition_e cond, void *data) return true; } -static bool __handle_sigchild(int fd, io_condition_e cond, void *data) +static void __handle_sigchild(int pid, void *user_data) { candidate_process_context_t *cpc; - struct signalfd_siginfo siginfo; - ssize_t s; char *appid; - int pid; - - do { - s = read(fd, &siginfo, sizeof(struct signalfd_siginfo)); - if (s == 0) - break; - - if (s != sizeof(struct signalfd_siginfo)) - break; - _signal_process_sigchld(&siginfo); - - pid = siginfo.ssi_code != SI_QUEUE ? siginfo.ssi_pid : siginfo.ssi_int; - - appid = g_hash_table_lookup(__pid_table, - GINT_TO_POINTER(pid)); - if (appid) { - security_manager_cleanup_app(appid, siginfo.ssi_uid, pid); - g_hash_table_remove(__pid_table, - GINT_TO_POINTER(pid)); - } + appid = g_hash_table_lookup(__pid_table, GINT_TO_POINTER(pid)); + if (appid) { + security_manager_cleanup_app(appid, getuid(), pid); + g_hash_table_remove(__pid_table, GINT_TO_POINTER(pid)); + } - cpc = __find_slot_from_pid(pid); + cpc = __find_slot_from_pid(pid); + if (cpc != NULL) { + cpc->pid = CANDIDATE_NONE; + __dispose_candidate_process(cpc); + __prepare_candidate_process(cpc->type, cpc->loader_id); + } else { + cpc = __find_hydra_slot_from_pid(pid); if (cpc != NULL) { - cpc->pid = CANDIDATE_NONE; - __dispose_candidate_process(cpc); + cpc->hydra_pid = HYDRA_NONE; + __dispose_hydra_process(cpc); __prepare_candidate_process(cpc->type, cpc->loader_id); - } else { - cpc = __find_hydra_slot_from_pid(pid); - if (cpc != NULL) { - cpc->hydra_pid = HYDRA_NONE; - __dispose_hydra_process(cpc); - __prepare_candidate_process(cpc->type, cpc->loader_id); - } } + } + cpc = __find_slot_from_caller_pid(pid); + while (cpc) { + __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id); cpc = __find_slot_from_caller_pid(pid); - while (cpc) { - __remove_slot(LAUNCHPAD_LOADER_TYPE_DYNAMIC, cpc->loader_id); - cpc = __find_slot_from_caller_pid(pid); - } - } while (s > 0); - - return true; + } } static bool __handle_label_monitor(int fd, io_condition_e cond, void *data) @@ -1841,7 +1818,7 @@ static int __check_caller_by_pid(int pid) int ret; char buf[PATH_MAX] = { 0, }; - ret = _proc_get_attr_by_pid(pid, buf, sizeof(buf)); + ret = _proc_get_attr(pid, buf, sizeof(buf)); if (ret < 0) return -1; @@ -2214,7 +2191,7 @@ end: close(clifd); if (pid > 0) { - _signal_send_app_launch_signal(pid, menu_info->appid); + _dbus_send_app_launch_signal(pid, menu_info->appid); g_hash_table_insert(__pid_table, GINT_TO_POINTER(pid), strdup(menu_info->appid)); } @@ -2449,26 +2426,6 @@ static int __init_launchpad_fd(int argc, char **argv) return 0; } -static int __init_sigchild_fd(void) -{ - int fd = -1; - - fd = _signal_get_sigchld_fd(); - if (fd < 0) { - _E("failed to get sigchld fd"); - return -1; - } - - __sigchild_channel = _io_channel_create(fd, IO_IN, - __handle_sigchild, NULL); - if (!__sigchild_channel) { - close(fd); - return -1; - } - - return 0; -} - static bool __on_directory_create(const char *event_name, uint32_t mask, void *user_data) { @@ -2967,12 +2924,14 @@ static int __before_loop(int argc, char **argv) return -1; } - ret = __init_sigchild_fd(); - if (ret != 0) { - _E("__init_sigchild_fd() failed"); + ret = _signal_init(); + if (ret < 0) { + _E("Failed to initialize signal"); return -1; } + _signal_set_sigchld_cb(__handle_sigchild, NULL); + ret = __init_launchpad_fd(argc, argv); if (ret != 0) { _E("__init_launchpad_fd() failed"); @@ -2993,6 +2952,10 @@ static int __before_loop(int argc, char **argv) if (ret != 0) _W("Failed to initialize config"); + ret = _dbus_init(); + if (ret != 0) + _W("Failed to initialize dbus"); + _inotify_init(); MAX_CPU_CHECK_COUNT = _config_get_int_value( @@ -3033,6 +2996,7 @@ static void __after_loop(void) _debug_fini(); _launcher_info_unload(launcher_info_list); + _dbus_fini(); _config_fini(); _inotify_fini(); _loader_info_dispose(app_defined_loader_info_list); @@ -3049,8 +3013,7 @@ static void __after_loop(void) if (__launchpad_channel) _io_channel_destroy(__launchpad_channel); - if (__sigchild_channel) - _io_channel_destroy(__sigchild_channel); + _signal_fini(); __sequencer_fini(); } diff --git a/src/launchpad/src/launchpad_dbus.c b/src/launchpad/src/launchpad_dbus.c new file mode 100644 index 0000000..f1446f1 --- /dev/null +++ b/src/launchpad/src/launchpad_dbus.c @@ -0,0 +1,278 @@ +/* + * 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 "launchpad_dbus.h" +#include "log_private.h" + +#define AUL_DBUS_PATH "/aul/dbus_handler" +#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" +#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" +#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" + +#define PENDING_ITEM_INTERVAL 1000 + +typedef enum { + APP_SIGNAL_DEAD, + APP_SIGNAL_LAUNCH, +} app_signal_e; + +typedef struct pending_item_s { + char *app_id; + int pid; + app_signal_e app_signal; +} pending_item_t; + +static GList *__pending_items; +static guint __timer; +static GDBusConnection *__conn; + +static void __set_pending_item_timer(void); + +static void __destroy_pending_item(gpointer data) +{ + pending_item_t *item = data; + + free(item->app_id); + free(item); +} + +static pending_item_t *__create_pending_item(const char *app_id, + int pid, app_signal_e app_signal) +{ + pending_item_t *item; + + item = calloc(1, sizeof(pending_item_t)); + if (!item) { + _E("Out of memory"); + return NULL; + } + + if (app_id) { + item->app_id = strdup(app_id); + if (!item->app_id) { + _E("Failed to duplicate app ID(%s)", app_id); + __destroy_pending_item(item); + return NULL; + } + } + + item->pid = pid; + item->app_signal = app_signal; + + return item; +} + +static GDBusConnection *__get_connection(void) +{ + GError *error = NULL; + + if (__conn) + return __conn; + + __conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!__conn) { + _E("g_bus_get_sync() is failed. error(%s)", + error ? error->message : "Unknown"); + g_clear_error(&error); + return NULL; + } + + return __conn; +} + +static int __emit_signal(const char *path, + const char *interface, + const char *signal, + GVariant *param) +{ + GDBusConnection *conn; + GError *error = NULL; + gboolean ret; + + conn = __get_connection(); + if (!conn) + return -1; + + ret = g_dbus_connection_emit_signal(conn, + NULL, + path, + interface, + signal, + param, + &error); + if (ret != TRUE) { + _E("g_dbus_connection_emit_signal() is failed. error(%s)", + error ? error->message : "Unknown"); + g_clear_error(&error); + return -1; + } + + ret = g_dbus_connection_flush_sync(conn, NULL, &error); + if (ret != TRUE) { + _E("g_dbus_connection_flush_sync() is failed. error(%s)", + error ? error->message : "Unknown"); + g_clear_error(&error); + return -1; + } + + return 0; +} + +static int __emit_app_launch_signal(int pid, const char *app_id) +{ + pending_item_t *item; + int ret; + + ret = __emit_signal(AUL_DBUS_PATH, + AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPLAUNCH_SIGNAL, + g_variant_new("(us)", pid, app_id)); + if (ret < 0) { + item = __create_pending_item(app_id, pid, APP_SIGNAL_LAUNCH); + if (!item) + return -ENOMEM; + + _W("Pend app launch signal. pid(%d), app_id(%s)", pid, app_id); + __pending_items = g_list_append(__pending_items, item); + __set_pending_item_timer(); + } else { + _D("App launch. pid(%d), app_id(%s)", pid, app_id); + } + + return 0; +} + +static int __emit_app_dead_signal(int pid) +{ + pending_item_t *item; + int ret; + + ret = __emit_signal(AUL_DBUS_PATH, + AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPDEAD_SIGNAL, + g_variant_new("(u)", pid)); + if (ret < 0) { + item = __create_pending_item(NULL, pid, APP_SIGNAL_DEAD); + if (!item) + return -ENOMEM; + + _W("Pend app dead signal. pid(%d)", pid); + __pending_items = g_list_append(__pending_items, item); + __set_pending_item_timer(); + } else { + _D("App dead. pid(%d)", pid); + } + + return 0; +} + +static gboolean __flush_pending_item(gpointer data) +{ + pending_item_t *item; + GList *iter; + int ret; + + if (!__pending_items) { + __timer = 0; + return G_SOURCE_REMOVE; + } + + iter = __pending_items; + while (iter) { + item = (pending_item_t *)iter->data; + if (item->app_signal == APP_SIGNAL_DEAD) + ret = __emit_app_dead_signal(item->pid); + else + ret = __emit_app_launch_signal(item->pid, item->app_id); + + if (ret < 0) + return G_SOURCE_CONTINUE; + + iter = g_list_next(iter); + __pending_items = g_list_remove(__pending_items, item); + __destroy_pending_item(item); + } + + __timer = 0; + return G_SOURCE_REMOVE; +} + +static void __set_pending_item_timer(void) +{ + if (__timer) + return; + + __timer = g_timeout_add(PENDING_ITEM_INTERVAL, + __flush_pending_item, NULL); +} + +static void __unset_pending_item_timer(void) +{ + if (!__timer) + return; + + g_source_remove(__timer); + __timer = 0; +} + +int _dbus_send_app_launch_signal(int pid, const char *app_id) +{ + if (pid <= 1 || !app_id) { + _E("Invalid parameter"); + return -EINVAL; + } + + return __emit_app_launch_signal(pid, app_id); +} + +int _dbus_send_app_dead_signal(int pid) +{ + if (pid <= 1) { + _E("Invalid parameter"); + return -EINVAL; + } + + return __emit_app_dead_signal(pid); +} + +int _dbus_init(void) +{ + GDBusConnection *conn; + + _D("DBUS_INIT"); + conn = __get_connection(); + if (!conn) + return -1; + + return 0; +} + +void _dbus_fini(void) +{ + _D("DBUS_FINI"); + if (__pending_items) + g_list_free_full(__pending_items, __destroy_pending_item); + + __unset_pending_item_timer(); + + if (__conn) + g_object_unref(__conn); +} diff --git a/src/launchpad/src/launchpad_io_channel.c b/src/launchpad/src/launchpad_io_channel.c index f20cb92..31529a3 100644 --- a/src/launchpad/src/launchpad_io_channel.c +++ b/src/launchpad/src/launchpad_io_channel.c @@ -28,6 +28,7 @@ struct io_channel_s { GIOChannel *io; guint tag; + bool do_close; int fd; io_channel_event_cb callback; void *user_data; @@ -96,8 +97,9 @@ static gboolean __io_event_cb(GIOChannel *source, GIOCondition condition, { io_channel_h channel = (io_channel_h)data; io_condition_e cond = __convert_g_io_condition(condition); + int fd = g_io_channel_unix_get_fd(source); - if (!channel->callback(channel->fd, cond, channel->user_data)) + if (!channel->callback(fd, cond, channel->user_data)) return G_SOURCE_REMOVE; return G_SOURCE_CONTINUE; @@ -134,6 +136,7 @@ io_channel_h _io_channel_create(int fd, io_condition_e cond, return NULL; } + channel->do_close = true; channel->fd = fd; channel->callback = callback; channel->user_data = user_data; @@ -152,8 +155,20 @@ void _io_channel_destroy(io_channel_h channel) if (channel->io) g_io_channel_unref(channel->io); - if (channel->fd) + if (channel->do_close && channel->fd > 0) close(channel->fd); free(channel); } + +int _io_channel_set_close_on_destroy(io_channel_h channel, bool do_close) +{ + if (!channel) { + _E("Invalid parameter"); + return -EINVAL; + } + + channel->do_close = do_close; + + return 0; +} diff --git a/src/launchpad/src/launchpad_signal.c b/src/launchpad/src/launchpad_signal.c index 8dbf565..5ee3067 100644 --- a/src/launchpad/src/launchpad_signal.c +++ b/src/launchpad/src/launchpad_signal.c @@ -1,317 +1,304 @@ /* - * Copyright (c) 2015 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2015 - 2020 Samsung Electronics Co., Ltd All Rights Reserved * - * Licensed under the Apache License, Version 2.0 (the License); + * 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, + * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE +#include +#include +#include #include #include -#include +#include #include #include -#include -#include +#include #include "launchpad_common.h" +#include "launchpad_dbus.h" +#include "launchpad_io_channel.h" +#include "launchpad_proc.h" #include "launchpad_signal.h" +#include "launchpad_socket.h" +#include "log_private.h" + +#define HYDRA_SIGCHLD_SOCK ".hydra-sigchld-sock" -#define AUL_DBUS_PATH "/aul/dbus_handler" -#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" -#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" -#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" -#define PENDING_SIGNAL_INTERVAL 1000 - -enum signal_e { - APP_DEAD, - APP_LAUNCH, -}; - -struct pending_signal { - char *appid; - int pid; - int signal; -}; - -static GDBusConnection *bus; -static sigset_t oldmask; -static GList *pending_signal_list; -static guint timeout_handle; - -static int __send_app_dead_signal(int dead_pid); -static int __send_app_launch_signal(int launch_pid, const char *app_id); - -static struct pending_signal *__create_pending_signal(const char *appid, - const int pid, const int signal) +static pid_t __pid; +static sigset_t __old_mask; +static socket_h __sigchld_socket; +static io_channel_h __sigchld_channel; +static socket_h __hydra_sigchld_socket; +static io_channel_h __hydra_sigchld_channel; +static signal_sigchld_cb __callback; +static void *__user_data; + +static void __socket_garbage_collector(void) { - struct pending_signal *handle; + DIR *dp; + struct dirent *dentry = NULL; + char path[PATH_MAX]; - handle = (struct pending_signal *)calloc(1, - sizeof(struct pending_signal)); - if (handle == NULL) { - _E("out of memory"); - return NULL; - } + snprintf(path, sizeof(path), "/run/aul/apps/%d", getuid()); + dp = opendir(path); + if (!dp) + return; - if (appid) { - handle->appid = strdup(appid); - if (handle->appid == NULL) { - _E("out of memory"); - free(handle); - return NULL; - } - } + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; - handle->pid = pid; - handle->signal = signal; + snprintf(path, sizeof(path), "/proc/%s", dentry->d_name); + if (access(path, F_OK) < 0) + _delete_sock_path(atoi(dentry->d_name), getuid()); + } + closedir(dp); +} - return handle; +static void __sigchld_action(int pid) +{ + _dbus_send_app_dead_signal(pid); + _delete_sock_path(pid, getuid()); + __socket_garbage_collector(); } -static void __destroy_pending_signal(struct pending_signal *handle) +static int __check_permission(int pid) { - if (handle == NULL) - return; + char buf[512] = { 0, }; + int ret; - if (handle->appid) - free(handle->appid); - free(handle); + ret = _proc_get_attr(pid, buf, sizeof(buf)); + if (ret < 0) + return -1; + + if (!strcmp(buf, "User") || + !strcmp(buf, "System") || + !strcmp(buf, "System::Privileged")) + return 0; + + _E("Permission denied. peer(%d:%s)", pid, buf); + return -1; } -static gboolean __flush_pending_signal(gpointer data) +static bool __hydra_sigchld_handler(int fd, io_condition_e cond, + void *user_data) { - struct pending_signal *handle; - GList *iter; + socket_h client_socket; + int caller_pid; + int pid = -1; int ret; - if (pending_signal_list == NULL) { - timeout_handle = 0; - return FALSE; + ret = _socket_accept(__hydra_sigchld_socket, &client_socket); + if (ret < 0) + return true; + + _socket_get_pid(client_socket, &caller_pid); + ret = __check_permission(caller_pid); + if (ret < 0) { + _socket_destroy(client_socket); + return true; } - iter = g_list_first(pending_signal_list); - while (iter) { - handle = (struct pending_signal *)iter->data; - iter = g_list_next(iter); - if (handle) { - if (handle->signal == APP_DEAD) { - ret = __send_app_dead_signal(handle->pid); - } else { - ret = __send_app_launch_signal(handle->pid, - handle->appid); - } - if (ret < 0) - return TRUE; - - pending_signal_list = g_list_remove(pending_signal_list, - handle); - __destroy_pending_signal(handle); - } + ret = _socket_read(client_socket, &pid, sizeof(pid)); + _socket_destroy(client_socket); + if (ret < 0) { + _E("Failed to read process id. ret(%d)", ret); + return true; } - timeout_handle = 0; + _W("[__SIGCHLD__] pid(%d)", pid); + __sigchld_action(pid); - return FALSE; + if (__callback) + __callback(pid, user_data); + + return true; } -static void __socket_garbage_collector(void) +static int __hydra_sigchld_init(void) { - DIR *dp; - struct dirent *dentry = NULL; - char tmp[PATH_MAX]; + char path[LAUNCHPAD_SOCKET_PATH_SIZE]; + io_channel_h channel; + socket_h socket; + int ret; + int fd; - snprintf(tmp, sizeof(tmp), "/run/aul/apps/%d", getuid()); - dp = opendir(tmp); - if (dp == NULL) - return; + snprintf(path, sizeof(path), "/run/aul/daemons/%u/%s", + getuid(), HYDRA_SIGCHLD_SOCK); + ret = _socket_create(path, false, &socket); + if (ret < 0) + return ret; - while ((dentry = readdir(dp)) != NULL) { - if (!isdigit(dentry->d_name[0])) - continue; + _socket_get_fd(socket, &fd); - snprintf(tmp, sizeof(tmp), "/proc/%s", dentry->d_name); - if (access(tmp, F_OK) < 0) { /* Flawfinder: ignore */ - _delete_sock_path(atoi(dentry->d_name), getuid()); - continue; - } + channel = _io_channel_create(fd, IO_IN | IO_PRI, + __hydra_sigchld_handler, NULL); + if (!channel) { + _socket_destroy(socket); + return -ENOMEM; } - closedir(dp); + + _io_channel_set_close_on_destroy(channel, false); + + __hydra_sigchld_socket = socket; + __hydra_sigchld_channel = channel; + + return 0; } -static int __send_app_dead_signal(int dead_pid) +static int __hydra_sigchld_fini(void) { - GError *err = NULL; - - /* send over session dbus for other applications */ - if (bus == NULL) { - bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); - if (bus == NULL) { - _E("Failed to connect to the D-BUS daemon: %s", - err->message); - g_error_free(err); - return -1; - } - } + if (__hydra_sigchld_channel) + _io_channel_destroy(__hydra_sigchld_channel); - if (g_dbus_connection_emit_signal(bus, - NULL, - AUL_DBUS_PATH, - AUL_DBUS_SIGNAL_INTERFACE, - AUL_DBUS_APPDEAD_SIGNAL, - g_variant_new("(u)", dead_pid), - &err) == FALSE) { - _E("g_dbus_connection_emit_signal() is failed: %s", - err->message); - g_error_free(err); - return -1; - } + if (__hydra_sigchld_socket) { + if (__pid != getpid()) + _socket_set_fd(__hydra_sigchld_socket, -1); - if (g_dbus_connection_flush_sync(bus, NULL, &err) == FALSE) { - _E("g_dbus_connection_flush_sync() is failed: %s", - err->message); - g_error_free(err); - return -1; + _socket_destroy(__hydra_sigchld_socket); } - _D("send_app_dead_signal_dbus done (pid=%d)", dead_pid); - return 0; } -static int __send_app_launch_signal(int launch_pid, const char *app_id) +static bool __sigchld_handler(int fd, io_condition_e cond, void *user_data) { - GError *err = NULL; - GVariant *param; - - if (bus == NULL) { - bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); - if (bus == NULL) { - _E("Failed to connect to the D-BUS daemon: %s", - err->message); - g_error_free(err); - return -1; - } - } + struct signalfd_siginfo info; + pid_t child_pid; + pid_t child_pgid; + int status; + int ret; - param = g_variant_new("(us)", launch_pid, app_id); - if (g_dbus_connection_emit_signal(bus, - NULL, - AUL_DBUS_PATH, - AUL_DBUS_SIGNAL_INTERFACE, - AUL_DBUS_APPLAUNCH_SIGNAL, - param, - &err) == FALSE) { - _E("g_dbus_connection_emit_signal() is failed: %s", - err->message); - g_error_free(err); - return -1; - } + do { + ret = _socket_read(__sigchld_socket, &info, sizeof(info)); + if (ret < 0) + break; - if (g_dbus_connection_flush_sync(bus, NULL, &err) == FALSE) { - _E("g_dbus_connection_flush_sync() is failed: %s", - err->message); - g_error_free(err); - return -1; - } + child_pgid = getpgid(info.ssi_pid); + _W("[__SIGCHLD__] pid(%d), pgid(%d), status(%d)", + info.ssi_pid, child_pgid, info.ssi_status); - _D("send_app_launch_signal_dbus done (pid=%d)", launch_pid); + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (child_pid == child_pgid) + killpg(child_pgid, SIGKILL); - return 0; + __sigchld_action(child_pid); + } + + if (__callback) + __callback(info.ssi_pid, __user_data); + } while (ret == 0); + + return true; } -int _signal_send_app_launch_signal(int launch_pid, const char *app_id) +static int __sigchld_init(void) { + io_channel_h channel; + socket_h socket; + sigset_t mask; + int sfd; int ret; - struct pending_signal *handle; - ret = __send_app_launch_signal(launch_pid, app_id); + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + + ret = sigprocmask(SIG_BLOCK, &mask, &__old_mask); if (ret < 0) { - handle = __create_pending_signal(app_id, launch_pid, - APP_LAUNCH); - pending_signal_list = g_list_append(pending_signal_list, - handle); - if (timeout_handle == 0) { - timeout_handle = g_timeout_add(PENDING_SIGNAL_INTERVAL, - __flush_pending_signal, NULL); - } - return -1; + ret = -errno; + _E("sigprocmask(SIG_BLOCK) is failed. errno(%d)", errno); + return ret; + } + + sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); + if (sfd < 0) { + ret = -errno; + _E("signalfd() is failed. errno(%d)", errno); + return ret; } + ret = _socket_create_with_fd(sfd, &socket); + if (ret < 0) { + close(sfd); + return ret; + } + + channel = _io_channel_create(sfd, IO_IN | IO_PRI, + __sigchld_handler, NULL); + if (!channel) { + _socket_destroy(socket); + return -ENOMEM; + } + _io_channel_set_close_on_destroy(channel, false); + + __sigchld_socket = socket; + __sigchld_channel = channel; + return 0; } -static int __sigchild_action(pid_t dead_pid) +static int __sigchld_fini(void) { int ret; - struct pending_signal *handle; - if (dead_pid <= 0) - return 0; + if (__sigchld_channel) + _io_channel_destroy(__sigchld_channel); - ret = __send_app_dead_signal(dead_pid); - if (ret < 0) { - handle = __create_pending_signal(NULL, dead_pid, APP_DEAD); - pending_signal_list = g_list_append(pending_signal_list, - handle); - if (timeout_handle == 0) { - timeout_handle = g_timeout_add(PENDING_SIGNAL_INTERVAL, - __flush_pending_signal, NULL); - } + if (__sigchld_socket) { + if (__pid != getpid()) + _socket_set_fd(__sigchld_socket, -1); + + _socket_destroy(__sigchld_socket); } - _delete_sock_path(dead_pid, getuid()); - __socket_garbage_collector(); + ret = sigprocmask(SIG_SETMASK, &__old_mask, NULL); + if (ret < 0) { + ret = -errno; + _E("sigprocmask(SIG_SETMASK) is failed. errno(%d)", errno); + return ret; + } return 0; } -void _signal_process_sigchld(struct signalfd_siginfo *info) +int _signal_set_sigchld_cb(signal_sigchld_cb callback, void *user_data) { - int status; - pid_t child_pid; - pid_t child_pgid; - - if (info->ssi_code != SI_QUEUE) { - child_pgid = getpgid(info->ssi_pid); - _D("dead_pid = %d pgid = %d signo = %d status = %d", info->ssi_pid, - child_pgid, info->ssi_signo, info->ssi_status); + __callback = callback; + __user_data = user_data; - while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { - if (child_pid == child_pgid) - killpg(child_pgid, SIGKILL); - __sigchild_action(child_pid); - } - } else { - _D("queued signal: dead_pid = %d signo = %d", info->ssi_int, - info->ssi_signo); - __sigchild_action(info->ssi_int); - } + return 0; } int _signal_init(void) { + int ret; int i; - GError *error = NULL; - bus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (!bus) { - _E("Failed to connect to the D-BUS daemon: %s", error->message); - g_error_free(error); - } + _D("SIGNAL_INIT"); + __pid = getpid(); + + ret = __sigchld_init(); + if (ret < 0) + return ret; - for (i = 0; i < _NSIG; i++) { + ret = __hydra_sigchld_init(); + if (ret < 0) + return ret; + + for (i = 0; i < _NSIG; ++i) { switch (i) { - /* controlled by sys-assert package*/ + /* controlled by sys-assert package*/ case SIGQUIT: case SIGILL: case SIGABRT: @@ -329,47 +316,17 @@ int _signal_init(void) return 0; } -int _signal_get_sigchld_fd(void) -{ - sigset_t mask; - int sfd; - - sigemptyset(&mask); - sigaddset(&mask, SIGCHLD); - - if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) - _E("failed to sigprocmask"); - - sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); - if (sfd == -1) { - _E("failed to create signal for SIGCHLD"); - return -1; - } - - return sfd; -} - -int _signal_unblock_sigchld(void) -{ - if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { - _E("SIG_SETMASK error"); - return -1; - } - - _D("SIGCHLD unblocked"); - return 0; -} - void _signal_fini(void) { #ifndef PRELOAD_ACTIVATE int i; - for (i = 0; i < _NSIG; i++) + for (i = 0; i < _NSIG; ++i) signal(i, SIG_DFL); #endif - if (bus) { - g_object_unref(bus); - bus = NULL; - } + + _D("SIGNAL_FINI"); + _signal_set_sigchld_cb(NULL, NULL); + __hydra_sigchld_fini(); + __sigchld_fini(); } -- 2.7.4