diff options
author | Sangyoon Jang <s89.jang@samsung.com> | 2015-12-08 11:47:36 +0900 |
---|---|---|
committer | Sangyoon Jang <s89.jang@samsung.com> | 2015-12-14 17:58:35 +0900 |
commit | 3829a47083ee911720141ab033e9839c0600ff60 (patch) | |
tree | ab6f439bd1a05be683eab296b626bd5828a184c9 | |
parent | 98b095b82ad012d708df36cf9e9f17a4d0a69a37 (diff) | |
download | aul-1-3829a47083ee911720141ab033e9839c0600ff60.tar.gz aul-1-3829a47083ee911720141ab033e9839c0600ff60.tar.bz2 aul-1-3829a47083ee911720141ab033e9839c0600ff60.zip |
Let amd wait application's launching using inotifysubmit/tizen/20151214.102546accepted/tizen/wearable/20151214.233950accepted/tizen/tv/20151214.233931accepted/tizen/mobile/20151214.233910
amd should not use busy waiting.
amd now monitors socket creation and returns result to caller when socket
is created.
if somebody request app_control to launching app, it will be pended
until the app launched(socket created).
Change-Id: I708cd6db27bc7e751e552be5507cda7c419d08e5
Signed-off-by: Sangyoon Jang <s89.jang@samsung.com>
-rw-r--r-- | am_daemon/amd_launch.c | 22 | ||||
-rw-r--r-- | am_daemon/amd_launch.h | 4 | ||||
-rw-r--r-- | am_daemon/amd_main.c | 2 | ||||
-rw-r--r-- | am_daemon/amd_request.c | 233 | ||||
-rw-r--r-- | am_daemon/amd_request.h | 2 | ||||
-rw-r--r-- | am_daemon/amd_status.c | 50 | ||||
-rw-r--r-- | am_daemon/amd_status.h | 2 | ||||
-rw-r--r-- | packaging/aul.spec | 2 |
8 files changed, 302 insertions, 15 deletions
diff --git a/am_daemon/amd_launch.c b/am_daemon/amd_launch.c index 4ceebacf..01811d4c 100644 --- a/am_daemon/amd_launch.c +++ b/am_daemon/amd_launch.c @@ -19,6 +19,7 @@ * */ +#include <stdbool.h> #include <signal.h> #include <bundle.h> #include <aul.h> @@ -92,9 +93,11 @@ static void __set_stime(bundle *kb) int _start_app_local_with_bundle(uid_t uid, const char *appid, bundle *kb) { + bool dummy; + __set_stime(kb); bundle_add(kb, AUL_K_APPID, appid); - return _start_app(appid, kb, APP_START, getpid(), uid, -1); + return _start_app(appid, kb, APP_START, getpid(), uid, -1, &dummy); } int _start_app_local(uid_t uid, const char *appid) @@ -719,7 +722,7 @@ int _get_pid_of_last_launched_ui_app() } int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, - uid_t caller_uid, int fd) + uid_t caller_uid, int fd, bool *pending) { int ret; const struct appinfo *ai; @@ -736,7 +739,6 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, char tmpbuf[MAX_PID_STR_BUFSZ]; const char *hwacc; char *caller_appid; - int delay_reply = 0; int lpid; int callee_status = -1; gboolean can_attach = FALSE; @@ -824,12 +826,13 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, if (caller_pid == pid) { SECURE_LOGD("caller process & callee process is same.[%s:%d]", appid, pid); pid = -ELOCALLAUNCH_ID; + __real_send(fd, pid); } else { aul_send_app_resume_request_signal(pid, appid, pkg_id, component_type); - if ((ret = __nofork_processing(cmd, pid, kb, fd)) < 0) + if ((ret = __nofork_processing(cmd, pid, kb, fd)) < 0) { pid = ret; - else - delay_reply = 1; + __real_send(fd, pid); + } } } else { if (callee_status == STATUS_DYING && pid > 0) { @@ -850,8 +853,10 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, pad_type = DEBUG_LAUNCHPAD_SOCK; pid = app_agent_send_cmd(caller_uid, pad_type, PAD_CMD_LAUNCH, kb); - if (pid > 0) + if (pid > 0) { + *pending = true; aul_send_app_launch_request_signal(pid, appid, pkg_id, component_type); + } } if (pid > 0) { @@ -867,8 +872,5 @@ int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, } } - if (!delay_reply) - __real_send(fd, pid); - return pid; } diff --git a/am_daemon/amd_launch.h b/am_daemon/amd_launch.h index 5c57d20a..adfb3753 100644 --- a/am_daemon/amd_launch.h +++ b/am_daemon/amd_launch.h @@ -22,6 +22,8 @@ #ifndef __AUL_AMD_LAUNCH_H_ #define __AUL_AMD_LAUNCH_H_ +#include <stdbool.h> + #include <bundle.h> #include "aul_util.h" #include "amd_appinfo.h" @@ -34,7 +36,7 @@ int _term_req_app(int pid, int clifd); int _term_bgapp(int pid, int clifd); int _term_sub_app(int pid); int _fake_launch_app(int cmd, int pid, bundle * kb, int clifd); -int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, uid_t caller_uid, int fd); +int _start_app(const char* appid, bundle* kb, int cmd, int caller_pid, uid_t caller_uid, int fd, bool *pend); int _start_app_local(uid_t uid, const char *appid); int _start_app_local_with_bundle(uid_t uid, const char *appid, bundle *kb); int _get_pid_of_last_launched_ui_app(); diff --git a/am_daemon/amd_main.c b/am_daemon/amd_main.c index 4942226a..4552ad9d 100644 --- a/am_daemon/amd_main.c +++ b/am_daemon/amd_main.c @@ -370,6 +370,7 @@ static int __app_dead_handler(int pid, void *data) __remove_item_running_list(pid, getuid()); _status_remove_app_info_list(pid, getuid()); + _request_flush_pending_request(pid); aul_send_app_terminated_signal(pid); if (restart) @@ -477,6 +478,7 @@ static int __init(void) restart_tbl = g_hash_table_new(g_str_hash, g_str_equal); _request_init(); + _status_init(); app_group_init(); if (vconf_notify_key_changed(VCONFKEY_SETAPPL_DEVOPTION_BGPROCESS, diff --git a/am_daemon/amd_request.c b/am_daemon/amd_request.c index 6f016710..4cb86b51 100644 --- a/am_daemon/amd_request.c +++ b/am_daemon/amd_request.c @@ -24,6 +24,7 @@ #include <dirent.h> #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <string.h> #include <dlfcn.h> #include <poll.h> @@ -57,13 +58,30 @@ #define PRIVILEGE_APPMANAGER_KILL_BGAPP "http://tizen.org/privilege/appmanager.kill.bgapp" #define MAX_NR_OF_DESCRIPTORS 2 +#define PENDING_REQUEST_TIMEOUT 5000 /* msec */ + static GHashTable *__socket_pair_hash = NULL; +static GHashTable *pending_table; + +struct pending_item { + int clifd; + int pid; + guint timer; + GList *pending_list; +}; + +struct request { + int clifd; + app_pkt_t *pkt; + struct ucred cr; +}; typedef int (*app_cmd_dispatch_func)(int clifd, const app_pkt_t *pkt, struct ucred *cr); static int __send_result_to_client(int fd, int res); static gboolean __request_handler(gpointer data); +static gboolean __timeout_pending_item(gpointer user_data); static int __send_message(int sock, const struct iovec *vec, int vec_size, const int *desc, int nr_desc) { @@ -642,6 +660,8 @@ static int __dispatch_app_start(int clifd, const app_pkt_t *pkt, struct ucred *c char *stat_caller = NULL; char *stat_tag = NULL; rua_stat_pkt_t *rua_stat_item = NULL; + bool pending = false; + struct pending_item *pending_item; kb = bundle_decode(pkt->data, pkt->len); if (kb == NULL) { @@ -658,7 +678,7 @@ static int __dispatch_app_start(int clifd, const app_pkt_t *pkt, struct ucred *c if (strcmp(state, "offline") && strcmp(state, "closing")) { ret = _start_app(appid, kb, pkt->cmd, cr->pid, - t_uid, clifd); + t_uid, clifd, &pending); } else { _E("uid:%d session is %s", t_uid, state); __real_send(clifd, AUL_R_ERROR); @@ -667,11 +687,24 @@ static int __dispatch_app_start(int clifd, const app_pkt_t *pkt, struct ucred *c } else { _E("request from root, treat as global user"); ret = _start_app(appid, kb, pkt->cmd, cr->pid, - GLOBAL_USER, clifd); + GLOBAL_USER, clifd, &pending); } } else { - ret = _start_app(appid, kb, pkt->cmd, cr->pid, cr->uid, clifd); + ret = _start_app(appid, kb, pkt->cmd, cr->pid, cr->uid, clifd, + &pending); } + + /* add pending list to wait app launched successfully */ + if (pending) { + pending_item = calloc(1, sizeof(struct pending_item)); + pending_item->clifd = clifd; + pending_item->pid = ret; + pending_item->timer = g_timeout_add(PENDING_REQUEST_TIMEOUT, + __timeout_pending_item, (gpointer)pending_item); + g_hash_table_insert(pending_table, GINT_TO_POINTER(ret), + pending_item); + } + if (ret > 0) { item = calloc(1, sizeof(item_pkt_t)); if (item == NULL) { @@ -1062,6 +1095,178 @@ static app_cmd_dispatch_func dispatch_table[APP_CMD_MAX] = { [AGENT_DEAD_SIGNAL] = __dispatch_agent_dead_signal, }; +static void __free_request(gpointer data) +{ + struct request *req = (struct request *)data; + + free(req->pkt); + free(req); +} + +static void __free_pending_item(struct pending_item *item) +{ + g_list_free_full(item->pending_list, __free_request); + if (g_main_context_find_source_by_user_data(NULL, item)) + g_source_remove(item->timer); + free(item); +} + +static void __process_pending_request(gpointer data, gpointer user_data) +{ + struct request *req = (struct request *)data; + + dispatch_table[req->pkt->cmd](req->clifd, req->pkt, &req->cr); +} + +static void __timeout_pending_request(gpointer data, gpointer user_data) +{ + struct request *req = (struct request *)data; + + __send_result_to_client(req->clifd, -1); +} + +static gboolean __timeout_pending_item(gpointer user_data) +{ + struct pending_item *item = (struct pending_item *)user_data; + + __send_result_to_client(item->clifd, item->pid); + g_list_foreach(item->pending_list, __timeout_pending_request, NULL); + + g_hash_table_remove(pending_table, GINT_TO_POINTER(item->pid)); + __free_pending_item(item); + + return FALSE; +} + +int _request_flush_pending_request(int pid) +{ + struct pending_item *item; + + item = (struct pending_item *)g_hash_table_lookup( + pending_table, GINT_TO_POINTER(pid)); + if (item == NULL) + return -1; + + __timeout_pending_item((gpointer)item); + + return 0; +} + +int _request_reply_for_pending_request(int pid) +{ + struct pending_item *item; + + item = (struct pending_item *)g_hash_table_lookup( + pending_table, GINT_TO_POINTER(pid)); + if (item == NULL) + return -1; + + __send_result_to_client(item->clifd, pid); + g_hash_table_remove(pending_table, GINT_TO_POINTER(pid)); + g_list_foreach(item->pending_list, __process_pending_request, NULL); + + __free_pending_item(item); + + return 0; +} + +static struct request *__get_request(int clifd, app_pkt_t *pkt, + struct ucred cr) +{ + struct request *req; + + req = malloc(sizeof(struct request)); + if (req == NULL) + return NULL; + + req->clifd = clifd; + req->pkt = calloc(1, AUL_PKT_HEADER_SIZE + pkt->len + 1); + memcpy(req->pkt, pkt, AUL_PKT_HEADER_SIZE + pkt->len + 1); + memcpy(&req->cr, &cr, sizeof(struct ucred)); + + return req; +} + +static int __check_app_is_running(struct request *req) +{ + bundle *b; + char *str; + int pid; + int ret = 0; + + b = bundle_decode(req->pkt->data, req->pkt->len); + if (b == NULL) + return -1; + + if (bundle_get_str(b, AUL_K_APPID, &str)) { + _E("cannot get target pid"); + bundle_free(b); + return -1; + } + + switch (req->pkt->cmd) { + case APP_RESUME_BY_PID: + case APP_TERM_BY_PID: + case APP_TERM_BY_PID_WITHOUT_RESTART: + case APP_KILL_BY_PID: + case APP_TERM_REQ_BY_PID: + case APP_TERM_BY_PID_ASYNC: + case APP_TERM_BGAPP_BY_PID: + case APP_PAUSE_BY_PID: + /* get pid */ + pid = atoi(str); + if (_status_app_get_appid_bypid(pid)) + ret = pid; + break; + default: + pid = _status_app_is_running(str, req->cr.uid); + if (pid > 0) + ret = pid; + } + + bundle_free(b); + + return ret; +} + +static int __check_request(struct request *req) +{ + int pid; + struct pending_item *item; + + /* TODO: categorize commands */ + if (req->pkt->cmd != APP_START && req->pkt->cmd != APP_OPEN && + req->pkt->cmd != APP_RESUME && + req->pkt->cmd != APP_RESUME_BY_PID && + req->pkt->cmd != APP_TERM_BY_PID && + req->pkt->cmd != APP_TERM_BY_PID_WITHOUT_RESTART && + req->pkt->cmd != APP_START_RES && + req->pkt->cmd != APP_KILL_BY_PID && + req->pkt->cmd != APP_TERM_REQ_BY_PID && + req->pkt->cmd != APP_TERM_BY_PID_ASYNC && + req->pkt->cmd != APP_TERM_BGAPP_BY_PID && + req->pkt->cmd != APP_PAUSE && + req->pkt->cmd != APP_PAUSE_BY_PID) + return 0; + + pid = __check_app_is_running(req); + if (pid < 0) + return -1; + else if (pid == 0) + return 0; + + if (_status_get_app_info_status(pid, req->cr.uid) == STATUS_DYING) + return 0; + + item = g_hash_table_lookup(pending_table, GINT_TO_POINTER(pid)); + if (item == NULL) + return 0; + + item->pending_list = g_list_append(item->pending_list, req); + + return 1; +} + static gboolean __request_handler(gpointer data) { GPollFD *gpollfd = (GPollFD *) data; @@ -1071,12 +1276,20 @@ static gboolean __request_handler(gpointer data) int clifd; struct ucred cr; const char *privilege; + struct request *req; if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) { _E("recv error"); return FALSE; } + req = __get_request(clifd, pkt, cr); + if (req == NULL) { + close(clifd); + free(pkt); + return TRUE; + } + if (cr.uid >= REGULAR_UID_MIN) { privilege = __convert_cmd_to_privilege(pkt->cmd); if (privilege) { @@ -1085,12 +1298,24 @@ static gboolean __request_handler(gpointer data) _E("request has been denied by smack"); ret = -EILLEGALACCESS; __real_send(clifd, ret); + __free_request(req); free(pkt); return TRUE; } } } + ret = __check_request(req); + if (ret < 0) { + __real_send(clifd, ret); + __free_request(req); + free(pkt); + return TRUE; + } else if (ret > 0) { + free(pkt); + return TRUE; + } + if (pkt->cmd >= 0 && pkt->cmd < APP_CMD_MAX && dispatch_table[pkt->cmd]) { if (dispatch_table[pkt->cmd](clifd, pkt, &cr) != 0) _E("callback returns FALSE : %d", pkt->cmd); @@ -1098,6 +1323,7 @@ static gboolean __request_handler(gpointer data) _E("Invalid packet or not supported command"); close(clifd); } + __free_request(req); free(pkt); return TRUE; @@ -1146,6 +1372,7 @@ int _request_init(void) GSource *src; __socket_pair_hash = g_hash_table_new_full(g_str_hash, g_str_equal, free, free); + pending_table = g_hash_table_new(g_direct_hash, g_direct_equal); fd = __create_sock_activation(); if (fd == -1) { diff --git a/am_daemon/amd_request.h b/am_daemon/amd_request.h index db963fed..a915986b 100644 --- a/am_daemon/amd_request.h +++ b/am_daemon/amd_request.h @@ -24,6 +24,8 @@ #define __AUL_AMD_REQUEST_H_ int _request_init(void); +int _request_reply_for_pending_request(int pid); +int _request_flush_pending_request(int pid); #endif diff --git a/am_daemon/amd_status.c b/am_daemon/amd_status.c index ddea373c..9a8a415b 100644 --- a/am_daemon/amd_status.c +++ b/am_daemon/amd_status.c @@ -25,10 +25,14 @@ #include <glib.h> #include <aul.h> #include <string.h> +#include <linux/limits.h> + +#include <gio/gio.h> #include "amd_config.h" #include "amd_status.h" #include "amd_appinfo.h" +#include "amd_request.h" #include "aul_util.h" #include "simple_util.h" #include "app_sock.h" @@ -460,3 +464,49 @@ int _status_get_pkgid_bypid(int fd, int pid) return 0; } + +static void __socket_monitor_cb(GFileMonitor *monitor, GFile *file, + GFile *other_file, GFileMonitorEvent event_type, + gpointer user_data) +{ + char *path; + char *p; + int pid; + + if (event_type != G_FILE_MONITOR_EVENT_CREATED) + return; + + path = g_file_get_path(file); + p = strrchr(path, '/'); + pid = atoi(p + 1); + + if (pid < 1) + return; + + _request_reply_for_pending_request(pid); + + g_free(path); +} + +int _status_init(void) +{ + char buf[PATH_MAX]; + GFile *file; + GFileMonitor *monitor; + GError *err = NULL; + + snprintf(buf, sizeof(buf), "/run/user/%d", getuid()); + file = g_file_new_for_path(buf); + if (file == NULL) + return -1; + + monitor = g_file_monitor_directory(file, G_FILE_MONITOR_NONE, + NULL, &err); + if (monitor == NULL) + return -1; + + g_signal_connect(monitor, "changed", G_CALLBACK(__socket_monitor_cb), + NULL); + + return 0; +} diff --git a/am_daemon/amd_status.h b/am_daemon/amd_status.h index ac1996c9..a7bd5811 100644 --- a/am_daemon/amd_status.h +++ b/am_daemon/amd_status.h @@ -35,7 +35,7 @@ char *_status_app_get_appid_bypid(int pid); int _status_send_running_appinfo_v2(int fd); //depcrecated int _status_get_appid_bypid(int fd, int pid); int _status_get_pkgid_bypid(int fd, int pid); - +int _status_init(void); //TODO : remove diff --git a/packaging/aul.spec b/packaging/aul.spec index 4f39cde1..3ad3a80d 100644 --- a/packaging/aul.spec +++ b/packaging/aul.spec @@ -22,6 +22,8 @@ Requires: tizen-platform-config BuildRequires: cmake BuildRequires: pkgconfig(dbus-glib-1) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(bundle) BuildRequires: pkgconfig(dlog) BuildRequires: xdgmime-devel, pkgconfig(xdgmime) |