summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHwankyu Jhun <h.jhun@samsung.com>2021-10-15 14:49:13 +0900
committerHwankyu Jhun <h.jhun@samsung.com>2021-11-03 12:27:54 +0900
commit182451f6deeef6f7227687a9de7726672fa21400 (patch)
tree0bc5d5238903391309d8899c4bd6ad546208247a
parentb3a890af0e4c6fc6447aa155dd683f4429c02c5f (diff)
downloadaul-1-182451f6deeef6f7227687a9de7726672fa21400.tar.gz
aul-1-182451f6deeef6f7227687a9de7726672fa21400.tar.bz2
aul-1-182451f6deeef6f7227687a9de7726672fa21400.zip
Fix aul app socket handler
After handling requests, AUL doesn't close the socket connection. AMD monitors the socket connection. When the connection is closed, AMD removes the status information of the application. This is a fallback of the zombie process of the application. Requires: - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/265335/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/265818/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/launchpad/+/265825/ Change-Id: Ia2b7e8ddaa2ced39862cb0fc085be1b08ff78d49 Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
-rw-r--r--include/aul_cmd.h2
-rw-r--r--include/aul_sock.h11
-rw-r--r--src/aul_cmd.c2
-rw-r--r--src/aul_launch.c225
-rw-r--r--src/aul_sock.c60
-rw-r--r--src/aul_worker.c56
-rw-r--r--src/aul_worker.h14
7 files changed, 305 insertions, 65 deletions
diff --git a/include/aul_cmd.h b/include/aul_cmd.h
index a654f43e..793db1c6 100644
--- a/include/aul_cmd.h
+++ b/include/aul_cmd.h
@@ -213,6 +213,8 @@ enum app_cmd {
PROC_GROUP_ADD = 169,
PROC_GROUP_REMOVE = 170,
+ APP_CONNECT = 171,
+
APP_CMD_MAX
};
diff --git a/include/aul_sock.h b/include/aul_sock.h
index 34235c4f..5dc8e89e 100644
--- a/include/aul_sock.h
+++ b/include/aul_sock.h
@@ -23,6 +23,7 @@
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
+#include <stdbool.h>
#include <bundle.h>
#include <aul_cmd.h>
@@ -132,6 +133,16 @@ int aul_sock_destroy_server(int fd);
*/
int aul_sock_send_result(int fd, int res);
+/**
+ * This API is only for Appfw internally.
+ */
+int aul_sock_send_result_v2(int fd, int res, bool do_close);
+
+/**
+ * This API is only for Appfw internally.
+ */
+int aul_sock_recv_reply_pkt_v2(int fd, app_pkt_t **pkt, bool do_close);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/aul_cmd.c b/src/aul_cmd.c
index 7ba85f04..daf62ec1 100644
--- a/src/aul_cmd.c
+++ b/src/aul_cmd.c
@@ -215,6 +215,8 @@ API const char *aul_cmd_convert_to_string(int cmd)
"PROC_GROUP_ADD",
"PROC_GROUP_REMOVE",
+ "APP_CONNECT",
+
"CUSTOM_COMMAND"
};
diff --git a/src/aul_launch.c b/src/aul_launch.c
index 7b5376ac..dd5acbce 100644
--- a/src/aul_launch.c
+++ b/src/aul_launch.c
@@ -41,6 +41,13 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+typedef struct client_channel_s {
+ int fd;
+ pid_t pid;
+ uid_t uid;
+ GRecMutex mutex;
+} client_channel_t;
+
struct aul_request_s {
int cmd;
int clifd;
@@ -72,10 +79,77 @@ typedef struct launch_context_s {
aul_handler aul;
subapp_handler subapp;
data_control_provider_handler dcp;
+ GList* clients;
+ GRecMutex mutex;
} launch_context;
static launch_context __context;
+static void __destroy_client_channel(gpointer data)
+{
+ client_channel_t *channel = data;
+
+ g_rec_mutex_lock(&channel->mutex);
+ g_rec_mutex_unlock(&channel->mutex);
+ g_rec_mutex_clear(&channel->mutex);
+
+ free(channel);
+}
+
+static client_channel_t *__create_client_channel(int fd, pid_t pid, uid_t uid)
+{
+ client_channel_t *channel;
+
+ channel = calloc(1, sizeof(client_channel_t));
+ if (!channel) {
+ _E("Out of memory");
+ return NULL;
+ }
+
+ g_rec_mutex_init(&channel->mutex);
+
+ channel->fd = fd;
+ channel->pid = pid;
+ channel->uid = uid;
+
+ return channel;
+}
+
+static void __add_client_channel(client_channel_t *channel)
+{
+ g_rec_mutex_lock(&__context.mutex);
+ __context.clients = g_list_append(__context.clients, channel);
+ g_rec_mutex_unlock(&__context.mutex);
+}
+
+static void __remove_client_channel(client_channel_t *channel)
+{
+ g_rec_mutex_lock(&__context.mutex);
+ __context.clients = g_list_remove(__context.clients, channel);
+ g_rec_mutex_unlock(&__context.mutex);
+}
+
+static client_channel_t *__find_client_channel(int fd)
+{
+ client_channel_t *channel;
+ GList *iter;
+
+ g_rec_mutex_lock(&__context.mutex);
+ iter = __context.clients;
+ while (iter) {
+ channel = iter->data;
+ if (channel->fd == fd) {
+ g_rec_mutex_unlock(&__context.mutex);
+ return channel;
+ }
+
+ iter = g_list_next(iter);
+ }
+ g_rec_mutex_unlock(&__context.mutex);
+
+ return NULL;
+}
+
static void __invoke_aul_handler(aul_type type, bundle *b)
{
if (__context.aul.callback)
@@ -250,6 +324,10 @@ static void __dispatch_watchdog_disable(aul_request_h req)
aul_watchdog_stop();
}
+static void __dispatch_app_connect(aul_request_h req)
+{
+}
+
static dispatcher __dispatcher[] = {
[APP_START] = __dispatch_app_start,
[APP_START_RES] = __dispatch_app_start,
@@ -280,6 +358,7 @@ static dispatcher __dispatcher[] = {
[APP_TERM_BG_INSTANCE] = __dispatch_app_term_bg_inst,
[WATCHDOG_ENABLE] = __dispatch_watchdog_enable,
[WATCHDOG_DISABLE] = __dispatch_watchdog_disable,
+ [APP_CONNECT] = __dispatch_app_connect,
};
static void __destroy_request(struct aul_request_s *req)
@@ -308,11 +387,19 @@ static struct aul_request_s *__create_request(int cmd, int clifd, bundle *b)
static int __send_result(struct aul_request_s *req, int res)
{
+ client_channel_t *channel;
int ret;
- if (req->cmd != WIDGET_GET_CONTENT && req->clifd > 0) {
- ret = aul_sock_send_result(req->clifd, res);
- req->clifd = -1;
+ if (req->cmd != WIDGET_GET_CONTENT && req->clifd >= 0) {
+ channel = __find_client_channel(req->clifd);
+ if (!channel) {
+ _E("Failed to find client channel. fd(%d)", req->clifd);
+ return -1;
+ }
+
+ g_rec_mutex_lock(&channel->mutex);
+ ret = aul_sock_send_result_v2(req->clifd, res, false);
+ g_rec_mutex_unlock(&channel->mutex);
if (ret < 0) {
_E("Failed to send result. cmd(%s:%d)",
aul_cmd_convert_to_string(req->cmd),
@@ -331,7 +418,6 @@ static gboolean __dispatch_request(gpointer data)
if (!__context.initialized) {
_W("Ignore request(%d)", req->cmd);
- __send_result(req, -1);
__destroy_request(req);
return G_SOURCE_REMOVE;
}
@@ -359,14 +445,72 @@ static gboolean __dispatch_request(gpointer data)
return G_SOURCE_REMOVE;
}
-static bool __worker_io_job_cb(int fd, void *user_data)
+static void __process_app_pkt(app_pkt_t *pkt, int clifd)
{
- aul_worker_h worker = user_data;
struct aul_request_s *req;
- app_pkt_t *pkt;
bundle *b = NULL;
- int clifd;
+
+ if (pkt->opt & AUL_SOCK_BUNDLE) {
+ b = bundle_decode(pkt->data, pkt->len);
+ if (!b) {
+ _E("Failed to decode the packet");
+ return;
+ }
+ }
+
+ req = __create_request(pkt->cmd, clifd, b);
+ if (!req) {
+ bundle_free(b);
+ return;
+ }
+
+ g_idle_add(__dispatch_request, req);
+}
+
+static bool __received_event_cb(int fd, int condition, void *user_data)
+{
+ aul_worker_h worker = user_data;
+ client_channel_t *channel;
+ app_pkt_t *pkt;
+ int ret;
+
+ channel = __find_client_channel(fd);
+ if (!channel) {
+ _E("Failed to find client channel. fd(%d)", fd);
+ return false;
+ }
+
+ if (condition & (AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL)) {
+ _E("IO error occurred. condition(%d), fd(%d)", condition, fd);
+ __remove_client_channel(channel);
+ __destroy_client_channel(channel);
+ return false;
+ }
+
+ g_rec_mutex_lock(&channel->mutex);
+ ret = aul_sock_recv_reply_pkt_v2(fd, &pkt, false);
+ g_rec_mutex_unlock(&channel->mutex);
+ if (ret != 0) {
+ _E("Failed to receive the packet. error(%d)", ret);
+ return true;
+ }
+
+ __process_app_pkt(pkt, fd);
+ aul_worker_add_anr_timer(worker, pkt->cmd);
+ free(pkt);
+
+ return true;
+}
+
+static bool __connected_event_cb(int fd, int condition, void *user_data)
+{
+ int cond = AUL_IO_IN | AUL_IO_HUP | AUL_IO_ERR | AUL_IO_NVAL;
+ aul_worker_h worker = user_data;
+ client_channel_t *channel = NULL;
struct ucred cr;
+ int clifd;
+ app_pkt_t *pkt;
+ int ret;
pkt = aul_sock_recv_pkt(fd, &clifd, &cr);
if (!pkt) {
@@ -374,44 +518,66 @@ static bool __worker_io_job_cb(int fd, void *user_data)
return true;
}
+ _W("pid(%d), clifd(%d), cmd(%d)", cr.pid, clifd, pkt->cmd);
if (pkt->cmd != WIDGET_GET_CONTENT) {
if (pkt->opt & AUL_SOCK_NOREPLY) {
close(clifd);
clifd = -1;
- }
- }
-
- if (pkt->opt & AUL_SOCK_BUNDLE) {
- b = bundle_decode(pkt->data, pkt->len);
- if (!b) {
- _E("Failed to decode the packet");
- if (clifd > 0)
+ } else {
+ channel = __create_client_channel(clifd,
+ cr.pid, cr.uid);
+ if (!channel) {
+ free(pkt);
close(clifd);
- free(pkt);
- return true;
+ return true;
+ }
+
+ __add_client_channel(channel);
}
}
- req = __create_request(pkt->cmd, clifd, b);
+ __process_app_pkt(pkt, clifd);
+ aul_worker_add_anr_timer(worker, pkt->cmd);
+
+ if (pkt->cmd == WIDGET_GET_CONTENT)
+ clifd = -1;
+
free(pkt);
- if (!req) {
- bundle_free(b);
+
+ if (clifd < 0)
return true;
- }
- aul_worker_add_anr_timer(worker, req->cmd);
- g_idle_add(__dispatch_request, req);
+ ret = aul_worker_add_io_job(worker, "client", clifd, cond,
+ __received_event_cb, worker);
+ if (ret < 0) {
+ _E("Failed to add io job. error(%d)", ret);
+ __remove_client_channel(channel);
+ __destroy_client_channel(channel);
+ return true;
+ }
return true;
}
static void __finalize_context(void)
{
+ if (!__context.initialized)
+ return;
+
if (__context.worker) {
aul_worker_destroy(__context.worker);
__context.worker = NULL;
}
+ g_rec_mutex_lock(&__context.mutex);
+ if (__context.clients) {
+ g_list_free_full(__context.clients, __destroy_client_channel);
+ __context.clients = NULL;
+ }
+
+ g_rec_mutex_unlock(&__context.mutex);
+ g_rec_mutex_clear(&__context.mutex);
+
__context.initialized = false;
}
@@ -420,20 +586,27 @@ static int __initialize_context(void)
int ret;
int fd;
+ if (__context.initialized) {
+ _E("Already initialized");
+ return AUL_R_OK;
+ }
+
fd = aul_initialize();
if (fd < 0) {
_E("Failed to initialize aul");
return fd;
}
+ g_rec_mutex_init(&__context.mutex);
+
__context.worker = aul_worker_create("aul+");
if (!__context.worker) {
__finalize_context();
return AUL_R_ERROR;
}
- ret = aul_worker_add_io_job(__context.worker, "AUL", fd,
- __worker_io_job_cb, __context.worker);
+ ret = aul_worker_add_io_job(__context.worker, "server", fd, AUL_IO_IN,
+ __connected_event_cb, __context.worker);
if (ret < 0) {
__finalize_context();
return ret;
diff --git a/src/aul_sock.c b/src/aul_sock.c
index c4e73595..49807581 100644
--- a/src/aul_sock.c
+++ b/src/aul_sock.c
@@ -625,20 +625,7 @@ API app_pkt_t *aul_sock_recv_pkt(int fd, int *clifd, struct ucred *cr)
API int aul_sock_recv_reply_pkt(int fd, app_pkt_t **ret_pkt)
{
- int ret;
-
- if (fd < 0 || fd > sysconf(_SC_OPEN_MAX))
- return -EINVAL;
-
- if (!ret_pkt) {
- close(fd);
- return -EINVAL;
- }
-
- ret = __recv_pkt(fd, ret_pkt);
- close(fd);
-
- return ret;
+ return aul_sock_recv_reply_pkt_v2(fd, ret_pkt, true);
}
static int __get_descriptors(struct cmsghdr *cmsg, struct msghdr *msg, int *fds, int maxdesc)
@@ -949,25 +936,44 @@ API int aul_sock_destroy_server(int fd)
API int aul_sock_send_result(int fd, int res)
{
- int r;
+ return aul_sock_send_result_v2(fd, res, true);
+}
- if (fd < 0) {
+API int aul_sock_send_result_v2(int fd, int res, bool do_close)
+{
+ int ret;
+
+ if (fd < 0 || fd > sysconf(_SC_OPEN_MAX)) {
_E("Invalid parameter");
return -EINVAL;
}
- r = send(fd, &res, sizeof(res), MSG_NOSIGNAL);
- if (r < 0) {
- if (errno == EPIPE) {
- _E("EPIPE error");
- close(fd);
- return r;
- }
+ ret = send(fd, &res, sizeof(res), MSG_NOSIGNAL);
+ if (ret < 0)
+ _E("Failed to send result. fd(%d), errno(%d)", fd, errno);
- _E("Failed to send result. fd(%d), errno(%d)",
- fd, errno);
+ if (do_close)
+ close(fd);
+
+ return ret;
+}
+
+API int aul_sock_recv_reply_pkt_v2(int fd, app_pkt_t **pkt, bool do_close)
+{
+ int ret;
+
+ if (fd < 0 || fd > sysconf(_SC_OPEN_MAX))
+ return -EINVAL;
+
+ if (!pkt) {
+ if (do_close)
+ close(fd);
+ return -EINVAL;
}
- close(fd);
- return 0;
+ ret = __recv_pkt(fd, pkt);
+ if (do_close)
+ close(fd);
+
+ return ret;
}
diff --git a/src/aul_worker.c b/src/aul_worker.c
index 151a9cdc..3593bb2c 100644
--- a/src/aul_worker.c
+++ b/src/aul_worker.c
@@ -170,6 +170,46 @@ static int __set_comm(const char *name)
return 0;
}
+static GIOCondition __convert_aul_io_condition(int condition)
+{
+ GIOCondition cond = 0;
+
+ if (condition & AUL_IO_IN)
+ cond |= G_IO_IN;
+ if (condition & AUL_IO_OUT)
+ cond |= G_IO_OUT;
+ if (condition & AUL_IO_PRI)
+ cond |= G_IO_PRI;
+ if (condition & AUL_IO_HUP)
+ cond |= G_IO_HUP;
+ if (condition & AUL_IO_ERR)
+ cond |= G_IO_ERR;
+ if (condition & AUL_IO_NVAL)
+ cond |= G_IO_NVAL;
+
+ return cond;
+}
+
+static int __convert_g_io_condition(GIOCondition condition)
+{
+ int cond = 0;
+
+ if (condition & G_IO_IN)
+ cond |= AUL_IO_IN;
+ if (condition & G_IO_OUT)
+ cond |= AUL_IO_OUT;
+ if (condition & G_IO_PRI)
+ cond |= AUL_IO_PRI;
+ if (condition & G_IO_HUP)
+ cond |= AUL_IO_HUP;
+ if (condition & G_IO_ERR)
+ cond |= AUL_IO_ERR;
+ if (condition & G_IO_NVAL)
+ cond |= AUL_IO_NVAL;
+
+ return cond;
+}
+
static gboolean __io_job_handler(GIOChannel *io, GIOCondition condition,
gpointer data)
{
@@ -177,6 +217,7 @@ static gboolean __io_job_handler(GIOChannel *io, GIOCondition condition,
struct job_s *job = (struct job_s *)data;
aul_worker_io_job_cb callback;
GSource *source;
+ int cond;
source = g_main_current_source();
if (!source || g_source_is_destroyed(source)) {
@@ -184,14 +225,9 @@ static gboolean __io_job_handler(GIOChannel *io, GIOCondition condition,
return G_SOURCE_REMOVE;
}
- if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) {
- _E("[__JOB__] name(%s), condition(%d)", job->name, condition);
- job->tag = 0;
- return G_SOURCE_REMOVE;
- }
-
+ cond = __convert_g_io_condition(condition);
callback = (aul_worker_io_job_cb)job->callback;
- if (callback(fd, job->user_data))
+ if (callback(fd, cond, job->user_data))
return G_SOURCE_CONTINUE;
_I("[__JOB__] name(%s)", job->name);
@@ -201,10 +237,10 @@ static gboolean __io_job_handler(GIOChannel *io, GIOCondition condition,
}
int aul_worker_add_io_job(aul_worker_h handle, const char *job_name,
- int fd, aul_worker_io_job_cb callback, void *user_data)
+ int fd, int condition, aul_worker_io_job_cb callback,
+ void *user_data)
{
- GIOCondition cond = G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR |
- G_IO_NVAL;
+ GIOCondition cond = __convert_aul_io_condition(condition);
struct aul_worker_s *worker = (struct aul_worker_s *)handle;
struct job_s *job;
GIOChannel *channel;
diff --git a/src/aul_worker.h b/src/aul_worker.h
index 42c7a309..c4a1c108 100644
--- a/src/aul_worker.h
+++ b/src/aul_worker.h
@@ -21,14 +21,24 @@
typedef void *aul_worker_h;
-typedef bool (*aul_worker_io_job_cb)(int fd, void *user_data);
+typedef enum {
+ AUL_IO_IN = 0x01,
+ AUL_IO_OUT = 0x02,
+ AUL_IO_PRI = 0x04,
+ AUL_IO_ERR = 0x10,
+ AUL_IO_HUP = 0x20,
+ AUL_IO_NVAL = 0x40,
+} aul_io_condition_e;
+
+typedef bool (*aul_worker_io_job_cb)(int fd, int condition, void *user_data);
aul_worker_h aul_worker_create(const char *name);
void aul_worker_destroy(aul_worker_h handle);
int aul_worker_add_io_job(aul_worker_h handle, const char *job_name,
- int fd, aul_worker_io_job_cb callback, void *user_data);
+ int fd, int condition, aul_worker_io_job_cb callback,
+ void *user_data);
int aul_worker_add_anr_timer(aul_worker_h handle, int cmd);