summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSangyoon Jang <s89.jang@samsung.com>2015-12-08 11:47:36 +0900
committerSangyoon Jang <s89.jang@samsung.com>2015-12-14 17:58:35 +0900
commit3829a47083ee911720141ab033e9839c0600ff60 (patch)
treeab6f439bd1a05be683eab296b626bd5828a184c9
parent98b095b82ad012d708df36cf9e9f17a4d0a69a37 (diff)
downloadaul-1-3829a47083ee911720141ab033e9839c0600ff60.tar.gz
aul-1-3829a47083ee911720141ab033e9839c0600ff60.tar.bz2
aul-1-3829a47083ee911720141ab033e9839c0600ff60.zip
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.c22
-rw-r--r--am_daemon/amd_launch.h4
-rw-r--r--am_daemon/amd_main.c2
-rw-r--r--am_daemon/amd_request.c233
-rw-r--r--am_daemon/amd_request.h2
-rw-r--r--am_daemon/amd_status.c50
-rw-r--r--am_daemon/amd_status.h2
-rw-r--r--packaging/aul.spec2
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)