From 526cd30c05737e583a70cf4a66c3a8016245c297 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 29 May 2020 11:27:37 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 From 45341ae63552d6ec64b8fe5b06e3e45d8013798b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 12 Jun 2020 10:32:09 +0900 Subject: [PATCH 08/16] Release version 0.15.4 Changes: - Fix setting LC_ALL env - Fix hydra sigchld handler Change-Id: If4b202bcb6687612df5e533c4d71352eb3fea7ba 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 736ef9b..7a2ec41 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.15.3 +Version: 0.15.4 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 1469feefc7c993363ac4df8668367423b3e9f09f Mon Sep 17 00:00:00 2001 From: changyu-choi Date: Thu, 18 Jun 2020 17:16:37 +0900 Subject: [PATCH 09/16] Limit error log from __get_connection Change-Id: I29bbbe56296a2ede7a8cb7f0422d9318ccf7b917 Signed-off-by: changyu-choi --- src/launchpad/src/launchpad_dbus.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/launchpad/src/launchpad_dbus.c b/src/launchpad/src/launchpad_dbus.c index f1446f1..171612b 100644 --- a/src/launchpad/src/launchpad_dbus.c +++ b/src/launchpad/src/launchpad_dbus.c @@ -29,6 +29,8 @@ #define PENDING_ITEM_INTERVAL 1000 +#define GET_CONNECTION_ERROR_THRESHOLD 10 +#define GET_CONNECTION_ERROR_MODULO 1000 typedef enum { APP_SIGNAL_DEAD, APP_SIGNAL_LAUNCH, @@ -83,14 +85,20 @@ static pending_item_t *__create_pending_item(const char *app_id, static GDBusConnection *__get_connection(void) { GError *error = NULL; + static unsigned int error_count = 0; if (__conn) return __conn; __conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); if (!__conn) { - _E("g_bus_get_sync() is failed. error(%s)", + error_count++; + if (error_count < GET_CONNECTION_ERROR_THRESHOLD || + error_count % GET_CONNECTION_ERROR_MODULO == 0) { + _E("g_bus_get_sync() is failed. error(%s)", error ? error->message : "Unknown"); + } + g_clear_error(&error); return NULL; } -- 2.7.4 From 3a80ec5627488f3b87494eea0698b1aac129df7f Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 19 Jun 2020 07:45:36 +0900 Subject: [PATCH 10/16] Reduce printing logs Change-Id: I8da9db42385a395aaf4a36d83ff27d48ffe1f7e8 Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_plugin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/src/launchpad_plugin.c b/src/common/src/launchpad_plugin.c index 912c19d..30f41c3 100644 --- a/src/common/src/launchpad_plugin.c +++ b/src/common/src/launchpad_plugin.c @@ -35,7 +35,8 @@ int _launchpad_plugin_prepare_app(const char *app_id, bundle *kb) ret = access(PATH_LAUNCHPAD_PLUGIN, F_OK); if (ret != 0) { - _D("plugin module does not exist. errno(%d)", errno); + if (errno != ENOENT) + _W("plugin module does not exist. errno(%d)", errno); return 0; } -- 2.7.4 From 8f36fe1f81baf48af89550021dfb267208174f9a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 19 Jun 2020 07:07:43 +0900 Subject: [PATCH 11/16] Fix bugs about sending dbus signal If flushing a pending signal is failed, launchpad should not create and store a new pending item from it. Change-Id: Ieb72efd4c16d92610f1aa7a20dc741cd16e0998b Signed-off-by: Hwankyu Jhun --- src/launchpad/src/launchpad_dbus.c | 60 +++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 24 deletions(-) diff --git a/src/launchpad/src/launchpad_dbus.c b/src/launchpad/src/launchpad_dbus.c index 171612b..e408b3c 100644 --- a/src/launchpad/src/launchpad_dbus.c +++ b/src/launchpad/src/launchpad_dbus.c @@ -146,48 +146,32 @@ static int __emit_signal(const char *path, 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; + if (ret < 0) + return ret; - _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); - } + _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; + if (ret < 0) + return ret; - _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); - } + _D("App dead. pid(%d)", pid); return 0; } @@ -243,22 +227,50 @@ static void __unset_pending_item_timer(void) int _dbus_send_app_launch_signal(int pid, const char *app_id) { + pending_item_t *item; + int ret; + if (pid <= 1 || !app_id) { _E("Invalid parameter"); return -EINVAL; } - return __emit_app_launch_signal(pid, app_id); + ret = __emit_app_launch_signal(pid, app_id); + if (ret < 0) { + item = __create_pending_item(app_id, pid, APP_SIGNAL_LAUNCH); + if (!item) + return -ENOMEM; + + _W("Pend app launch signal. pid(%d), app_id(%s)", pid, app_id); + __pending_items = g_list_append(__pending_items, item); + __set_pending_item_timer(); + } + + return 0; } int _dbus_send_app_dead_signal(int pid) { + pending_item_t *item; + int ret; + if (pid <= 1) { _E("Invalid parameter"); return -EINVAL; } - return __emit_app_dead_signal(pid); + ret = __emit_app_dead_signal(pid); + if (ret < 0) { + item = __create_pending_item(NULL, pid, APP_SIGNAL_DEAD); + if (!item) + return -ENOMEM; + + _W("Pend app dead signal. pid(%d)", pid); + __pending_items = g_list_append(__pending_items, item); + __set_pending_item_timer(); + } + + return 0; } int _dbus_init(void) -- 2.7.4 From 6d9d7ba1328b71a35fb57850efba49bb47f256d2 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 18 Jun 2020 17:18:39 +0900 Subject: [PATCH 12/16] Fix standard I/O redirection If calling sd_journal_stream_fd() is failed, the child process uses the interitance of file descriptors. Change-Id: Ia37c1ca586d735280cc07298088c00c93815b2aa Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_common.c | 91 +++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index e41a391..d2bf965 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -923,53 +923,80 @@ int _close_all_fds(void) return 0; } -int _setup_stdio(const char *ident) +static int __redirect_stdin(void) { + int ret; int fd; - /* stdin */ fd = open(PATH_DEV_NULL, O_RDONLY | O_NOCTTY); if (fd < 0) { - _W("Failed to open /dev/null - err(%d)", errno); - return -1; - } - if (dup2(fd, STDIN_FILENO) < 0) { - _W("Failed to duplicate fd - oldfd(%d), newfd(%d)", - fd, STDIN_FILENO); + ret = -errno; + _E("open(%s) is failed. errno(%d)", PATH_DEV_NULL, errno); + return ret; } + + ret = dup2(fd, STDIN_FILENO); + if (ret < 0) + _W("dup2(%d, 0) is failed. errno(%d)", fd, errno); + close(fd); + return ret; +} + +static int __redirect_stdout(const char *ident) +{ + int ret; + int fd; - /* stdout */ - fd = sd_journal_stream_fd(ident, LOG_INFO, false); + fd = sd_journal_stream_fd(ident, LOG_INFO, 0); if (fd < 0) { - _W("Failed to connect journal socket - err(%d)", errno); - fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY); - if (fd < 0) { - _W("Failed to open /dev/null - err(%d)", errno); - return -1; - } - } - if (dup2(fd, STDOUT_FILENO) < 0) { - _W("Failed to duplicate fd - oldfd(%d), newfd(%d)", - fd, STDOUT_FILENO); + _W("sd_journal_stream_fd() is failed. error(%d)", fd); + return fd; } + + ret = dup2(fd, STDOUT_FILENO); + if (ret < 0) + _W("dup(%d, 1) is failed. errno(%d)", fd, errno); + close(fd); + return ret; +} - /* stderr */ - fd = sd_journal_stream_fd(ident, LOG_INFO, false); +static int __redirect_stderr(const char *ident) +{ + int ret; + int fd; + + fd = sd_journal_stream_fd(ident, LOG_WARNING, 0); if (fd < 0) { - _W("Failed to connect journal socket - err(%d)", errno); - fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY); - if (fd < 0) { - _W("Failed to open /dev/null - err(%d)", errno); - return -1; - } - } - if (dup2(fd, STDERR_FILENO) < 0) { - _W("Failed to duplicate fd - oldfd(%d), newfd(%d)", - fd, STDERR_FILENO); + _W("sd_journal_stream_fd() is failed. error(%d)", fd); + return fd; } + + ret = dup2(fd, STDERR_FILENO); + if (ret < 0) + _W("dup(%d, 2) is failed. errno(%d)", fd, errno); + close(fd); + return ret; + +} + +int _setup_stdio(const char *ident) +{ + int ret; + + ret = __redirect_stdin(); + if (ret < 0) + return ret; + + ret = __redirect_stdout(ident); + if (ret < 0) + return ret; + + ret = __redirect_stderr(ident); + if (ret < 0) + return ret; return 0; } -- 2.7.4 From 99464b08a3a13fd9e498a5d8d76c8bcb74047270 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 19 Jun 2020 08:33:49 +0900 Subject: [PATCH 13/16] Release version 0.15.5 Changes: - Limit error log from __get_connection - Reduce printing logs - Fix bugs about sending dbus signal - Fix standard I/O redirection Change-Id: If8157766ddc65e2c9ca55f61be76e825faacb6c5 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 7a2ec41..b0c679d 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.15.4 +Version: 0.15.5 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 9996f39b1d9d581fcb810dc0b031613637cd2f5d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 23 Jun 2020 10:21:15 +0900 Subject: [PATCH 14/16] Check the error value Before printing error logs If the error value is -ENOENT(No such file or directory), the process doesn't print the error logs. Change-Id: I15548f966b4c28928f0f460c4be5a611df57503d Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index d2bf965..fdb2455 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -950,7 +950,8 @@ static int __redirect_stdout(const char *ident) fd = sd_journal_stream_fd(ident, LOG_INFO, 0); if (fd < 0) { - _W("sd_journal_stream_fd() is failed. error(%d)", fd); + if (fd != -ENOENT) + _W("sd_journal_stream_fd() is failed. error(%d)", fd); return fd; } @@ -969,7 +970,8 @@ static int __redirect_stderr(const char *ident) fd = sd_journal_stream_fd(ident, LOG_WARNING, 0); if (fd < 0) { - _W("sd_journal_stream_fd() is failed. error(%d)", fd); + if (fd != -ENOENT) + _W("sd_journal_stream_fd() is failed. error(%d)", fd); return fd; } -- 2.7.4 From 4ec25e48dc1c0abc206176e6832bfb1ea8f6126b Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 24 Jun 2020 07:33:45 +0900 Subject: [PATCH 15/16] Fix SMACK error When calling sd_journal_stream_fd() is failed, the child process used the fds of the parent. It causes SMACK errors. To prevent SMACK errors, the child process uses "/dev/null" for standard I/O redirection if calling sd_journal_stream_fd() is failed. Change-Id: Ia1816c552c8d417317d031d3945c9f89a86edb40 Signed-off-by: Hwankyu Jhun --- src/common/src/launchpad_common.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/src/common/src/launchpad_common.c b/src/common/src/launchpad_common.c index fdb2455..1521634 100644 --- a/src/common/src/launchpad_common.c +++ b/src/common/src/launchpad_common.c @@ -952,12 +952,22 @@ static int __redirect_stdout(const char *ident) if (fd < 0) { if (fd != -ENOENT) _W("sd_journal_stream_fd() is failed. error(%d)", fd); - return fd; + fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY); + if (fd < 0) { + ret = -errno; + _E("open(%s) is failed. errno(%d)", + PATH_DEV_NULL, errno); + close(STDOUT_FILENO); + return ret; + } } ret = dup2(fd, STDOUT_FILENO); - if (ret < 0) - _W("dup(%d, 1) is failed. errno(%d)", fd, errno); + if (ret < 0) { + ret = -errno; + _E("dup(%d, 1) is failed. errno(%d)", fd, errno); + close(STDOUT_FILENO); + } close(fd); return ret; @@ -972,12 +982,22 @@ static int __redirect_stderr(const char *ident) if (fd < 0) { if (fd != -ENOENT) _W("sd_journal_stream_fd() is failed. error(%d)", fd); - return fd; + fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY); + if (fd < 0) { + ret = -errno; + _E("open(%s) is failed. errno(%d)", + PATH_DEV_NULL, errno); + close(STDERR_FILENO); + return ret; + } } ret = dup2(fd, STDERR_FILENO); - if (ret < 0) - _W("dup(%d, 2) is failed. errno(%d)", fd, errno); + if (ret < 0) { + ret = -errno; + _E("dup(%d, 2) is failed. errno(%d)", fd, errno); + close(STDERR_FILENO); + } close(fd); return ret; -- 2.7.4 From 42ec3f45f044911da2dfda34e67102ff06424a7a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 24 Jun 2020 08:36:50 +0900 Subject: [PATCH 16/16] Release version 0.15.6 Changes: - Check the error value Before printing error logs - Fix SMACK error Change-Id: I9d40a9bd655b421d2e71e9e74247b8847a56a408 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 b0c679d..0c0cb55 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.15.5 +Version: 0.15.6 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4