Move app dead handler to app status 18/266018/3
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 4 Nov 2021 05:50:48 +0000 (14:50 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 4 Nov 2021 06:22:44 +0000 (15:22 +0900)
The pid number is not always increased sequentially.
Currently, the __dead_timeout_handler() function calls
the __app_dead_handler() function to clean up the app status.
If the process ID is reused after the application is terminated,
the __dead_timeout_handler() function will be operated incorrectly.
To handle the socket disconnected event properly, the timer is managed
by the app status handle. When releasing the app status handle,
the timer of the __dead_timeout_handler() function will be removed.

Change-Id: Ie45601948b8dc975c343db9d77f297005df35fe0
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/lib/amd_app_status.c
src/lib/amd_main.c

index 7217471..7576b20 100644 (file)
@@ -35,6 +35,7 @@
 
 #include "amd_api_noti.h"
 #include "amd_app_com.h"
+#include "amd_app_request_broker.h"
 #include "amd_app_status.h"
 #include "amd_appinfo.h"
 #include "amd_cynara.h"
@@ -82,6 +83,7 @@ struct app_status_s {
        bool debug_mode;
        guint timer;
        int real_pid;
+       guint disconn_timer;
 };
 
 struct fault_app_s {
@@ -97,6 +99,12 @@ struct vconf_context_s {
        guint timer;
 };
 
+struct restart_info_s {
+       char *appid;
+       int count;
+       guint timer;
+};
+
 static GSList *app_status_list;
 static GHashTable *pkg_status_table;
 static int limit_bg_uiapps;
@@ -104,9 +112,185 @@ static char *home_appid;
 static GHashTable *__wd_table;
 static inotify_watch_info_h __wh;
 static struct vconf_context_s __vconf;
+static GHashTable *__restart_table;
 
 static app_status_h __find_app_status(int pid);
 
+static gboolean __restart_timeout_handler(gpointer user_data)
+{
+       struct restart_info_s *info = user_data;
+
+       _I("info(%p), appid(%s)", info, info->appid);
+       info->timer = 0;
+       g_hash_table_remove(__restart_table, info->appid);
+       return G_SOURCE_REMOVE;
+}
+
+static void __destroy_restart_info(gpointer user_data)
+{
+       struct restart_info_s *info = user_data;
+
+       if (info->timer != 0)
+               g_source_remove(info->timer);
+
+       free(info->appid);
+       free(info);
+}
+
+static struct restart_info_s *__create_restart_info(const char *appid)
+{
+       struct restart_info_s *info;
+
+       info = calloc(1, sizeof(struct restart_info_s));
+       if (!info) {
+               _E("Out of memory");
+               return NULL;
+       }
+
+       info->appid = strdup(appid);
+       if (!info->appid) {
+               _E("Out of memory");
+               __destroy_restart_info(info);
+               return NULL;
+       }
+
+       info->timer = g_timeout_add_seconds(10, __restart_timeout_handler,
+                       info);
+       if (info->timer == 0) {
+               _E("g_timeout_add_seconds() is failed");
+               __destroy_restart_info(info);
+               return NULL;
+       }
+
+       info->count = 1;
+
+       return info;
+}
+
+static bool __check_restart(const char *appid)
+{
+       struct restart_info_s *info;
+
+       info = g_hash_table_lookup(__restart_table, appid);
+       if (!info) {
+               info = __create_restart_info(appid);
+               if (!info) {
+                       _E("Failed to create restart info. appid(%s)", appid);
+                       return false;
+               }
+
+               _D("info(%p), appid(%s), count(%d)", info, appid, info->count);
+               g_hash_table_insert(__restart_table, info->appid, info);
+       } else {
+               info->count++;
+               _W("info(%p), appid(%s), count(%d)", info, appid, info->count);
+               if (info->count > 5) {
+                       g_hash_table_remove(__restart_table, info->appid);
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+static bool __can_restart_app(const char *appid, uid_t uid)
+{
+       const char *comp_type;
+       const char *status;
+       struct appinfo *ai;
+       int enablement;
+       int restart;
+       int ret;
+
+       _D("appid(%s)", appid);
+       ai = _appinfo_find(uid, appid);
+       if (!ai)
+               return false;
+
+       comp_type = _appinfo_get_value(ai, AIT_COMPTYPE);
+       if (!comp_type || strcmp(comp_type, APP_TYPE_SERVICE) != 0)
+               return false;
+
+       ret = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enablement);
+       if (ret == 0 && !(enablement & APP_ENABLEMENT_MASK_ACTIVE)) {
+               _W("%s is disabled", appid);
+               return false;
+       }
+
+       status = _appinfo_get_value(ai, AIT_STATUS);
+       if (status && !strcmp(status, "blocking")) {
+               _appinfo_set_value(ai, AIT_STATUS, "restart");
+       } else if (status && !strcmp(status, "norestart")) {
+               _appinfo_set_value(ai, AIT_STATUS, "installed");
+       } else {
+               ret = _appinfo_get_int_value(ai, AIT_RESTART, &restart);
+               if (ret == 0 && restart && __check_restart(appid))
+                       return true;
+       }
+
+       return false;
+}
+
+static int __app_dead_handler(int pid, void *user_data)
+{
+       app_status_h app_status;
+       char appid_buf[256];
+       const char *appid;
+       char buf[128];
+       bool restart;
+       uid_t uid;
+
+       if (pid <= 0)
+               return 0;
+
+       app_status = _app_status_find(pid);
+       if (!app_status)
+               return 0;
+
+       appid = _app_status_get_appid(app_status);
+       _W("APP_DEAD_SIGNAL appid(%s), pid(%d)", appid, pid);
+
+       uid = _app_status_get_uid(app_status);
+       _noti_send(AMD_NOTI_MSG_MAIN_APP_DEAD, pid, uid, app_status, NULL);
+       restart = __can_restart_app(appid, uid);
+       if (restart)
+               snprintf(appid_buf, sizeof(appid_buf), "%s", appid);
+
+       _request_flush_pending_request(pid);
+       _app_status_cleanup(app_status);
+
+       if (restart)
+               _launch_start_app_local(uid, appid_buf);
+
+       snprintf(buf, sizeof(buf), "%d", pid);
+       _util_save_log("TERMINATED", buf);
+       return 0;
+}
+
+static gboolean __dead_timeout_handler(gpointer user_data)
+{
+       app_status_h app_status = user_data;
+
+       _E("Timer expired. appid(%s), pid(%d)",
+                       app_status->appid, app_status->pid);
+       app_status->disconn_timer = 0;
+       __app_dead_handler(app_status->pid, NULL);
+       return G_SOURCE_REMOVE;
+}
+
+static int __disconnected_event_cb(int pid, void *user_data)
+{
+       app_status_h app_status;
+
+       app_status = _app_status_find(pid);
+       if (!app_status)
+               return -1;
+
+       app_status->disconn_timer = g_timeout_add_seconds(10,
+                       __dead_timeout_handler, app_status);
+       return 0;
+}
+
 static int __get_managed_uiapp_cnt(void)
 {
        GSList *iter;
@@ -351,6 +535,8 @@ static void __destroy_app_status(struct app_status_s *app_status)
                g_hash_table_destroy(app_status->extras);
        if (app_status->timer)
                g_source_remove(app_status->timer);
+       if (app_status->disconn_timer)
+               g_source_remove(app_status->disconn_timer);
 
        free(app_status);
 }
@@ -2625,10 +2811,29 @@ static gboolean __vconf_init_handler(gpointer data)
        return G_SOURCE_REMOVE;
 }
 
+static int __listen_app_dead_signal(void *user_data)
+{
+       if (aul_listen_app_dead_signal(__app_dead_handler, user_data) < 0)
+               return -1;
+
+       return 0;
+}
+
 int _app_status_init(void)
 {
        int ret;
 
+       _signal_add_ready_cb(__listen_app_dead_signal, NULL);
+       _app_request_broker_set_disconnected_event_cb(__disconnected_event_cb,
+                       NULL);
+
+       __restart_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                       NULL, __destroy_restart_info);
+       if (!__restart_table) {
+               _E("g_hash_table_new_full() is failed");
+               return -1;
+       }
+
        __wd_table = g_hash_table_new_full(g_direct_hash, g_direct_equal,
                        NULL, __remove_inotify_watch);
        if (__wd_table == NULL) {
@@ -2685,6 +2890,11 @@ int _app_status_finish(void)
        if (__wd_table)
                g_hash_table_destroy(__wd_table);
 
+       if (__restart_table)
+               g_hash_table_destroy(__restart_table);
+
+       aul_listen_app_dead_signal(NULL, NULL);
+
        return 0;
 }
 
index b0e61c4..9fd990b 100644 (file)
@@ -35,7 +35,6 @@
 #include "amd_app_control.h"
 #include "amd_app_lifecycle.h"
 #include "amd_app_property.h"
-#include "amd_app_request_broker.h"
 #include "amd_app_status.h"
 #include "amd_appinfo.h"
 #include "amd_boot_manager.h"
 typedef int (*amd_mod_init_cb)(void);
 typedef void (*amd_mod_fini_cb)(void);
 
-struct restart_info {
-       char *appid;
-       int count;
-       guint timer;
-};
-
-static GHashTable *restart_tbl;
 static GList *so_handles;
 static sigset_t old_mask;
 
-static gboolean __restart_timeout_handler(void *data)
-{
-       struct restart_info *ri = (struct restart_info *)data;
-
-       _D("ri (%p)", ri);
-       _D("appid (%s)", ri->appid);
-
-       g_hash_table_remove(restart_tbl, ri->appid);
-       free(ri->appid);
-       free(ri);
-
-       return FALSE;
-}
-
-static bool __check_restart(const char *appid)
-{
-       struct restart_info *ri = NULL;
-       char err_buf[1024];
-
-       ri = g_hash_table_lookup(restart_tbl, appid);
-       if (!ri) {
-               ri = calloc(1, sizeof(struct restart_info));
-               if (!ri) {
-                       _E("create restart info: %s",
-                               strerror_r(errno, err_buf, sizeof(err_buf)));
-                       return false;
-               }
-               ri->appid = strdup(appid);
-               if (ri->appid == NULL) {
-                       _E("Out of memory");
-                       free(ri);
-                       return false;
-               }
-               ri->count = 1;
-               g_hash_table_insert(restart_tbl, ri->appid, ri);
-
-               _D("ri (%p)", ri);
-               _D("appid (%s)", appid);
-
-               ri->timer = g_timeout_add(10 * 1000, __restart_timeout_handler,
-                               ri);
-       } else {
-               ri->count++;
-               _D("count (%d)", ri->count);
-               if (ri->count > 5) {
-                       g_source_remove(ri->timer);
-                       g_hash_table_remove(restart_tbl, ri->appid);
-                       free(ri->appid);
-                       free(ri);
-                       return false;
-               }
-       }
-       return true;
-}
-
-static bool __can_restart_app(const char *appid, uid_t uid)
-{
-       const char *pkg_status;
-       const char *component_type;
-       struct appinfo *ai;
-       int r;
-       int val = 0;
-       int enable = 1;
-
-       _D("appid: %s", appid);
-       ai = _appinfo_find(uid, appid);
-       if (!ai)
-               return false;
-
-       component_type = _appinfo_get_value(ai, AIT_COMPTYPE);
-       if (!component_type)
-               return false;
-
-       if (strcmp(component_type, APP_TYPE_SERVICE) != 0)
-               return false;
-
-       r = _appinfo_get_int_value(ai, AIT_ENABLEMENT, &enable);
-       if (r == 0 && !(enable & APP_ENABLEMENT_MASK_ACTIVE)) {
-               _D("Disabled");
-               return false;
-       }
-
-       pkg_status = _appinfo_get_value(ai, AIT_STATUS);
-       if (pkg_status && strcmp(pkg_status, "blocking") == 0) {
-               _appinfo_set_value(ai, AIT_STATUS, "restart");
-       } else if (pkg_status && strcmp(pkg_status, "norestart") == 0) {
-               _appinfo_set_value(ai, AIT_STATUS, "installed");
-       } else {
-               r = _appinfo_get_int_value(ai, AIT_RESTART, &val);
-               if (r == 0 && val && __check_restart(appid))
-                       return true;
-       }
-
-       return false;
-}
-
-static int __app_dead_handler(int pid, void *data)
-{
-       bool restart = false;
-       char *appid = NULL;
-       const char *tmp_appid;
-       app_status_h app_status;
-       uid_t uid;
-       char buf[MAX_LOCAL_BUFSZ];
-
-       if (pid <= 0)
-               return 0;
-
-       app_status = _app_status_find(pid);
-       if (app_status == NULL)
-               return 0;
-
-       _W("APP_DEAD_SIGNAL : %d", pid);
-
-       uid = _app_status_get_uid(app_status);
-       _noti_send(AMD_NOTI_MSG_MAIN_APP_DEAD, pid, uid, app_status, NULL);
-       tmp_appid = _app_status_get_appid(app_status);
-       if (tmp_appid == NULL)
-               return 0;
-
-       uid = _app_status_get_uid(app_status);
-       restart = __can_restart_app(tmp_appid, uid);
-       if (restart) {
-               appid = strdup(tmp_appid);
-               if (appid == NULL)
-                       _W("Out of memory");
-       }
-
-       _request_flush_pending_request(pid);
-       _app_status_cleanup(app_status);
-
-       if (restart)
-               _launch_start_app_local(uid, appid);
-       if (appid)
-               free(appid);
-
-       snprintf(buf, sizeof(buf), "%d", pid);
-       _util_save_log("TERMINATED", buf);
-       return 0;
-}
-
-static gboolean __dead_timeout_handler(gpointer user_data)
-{
-       int pid = GPOINTER_TO_INT(user_data);
-
-       __app_dead_handler(pid, NULL);
-       return G_SOURCE_REMOVE;
-}
-
-static int __disconnected_event_cb(int pid, void *user_data)
-{
-       g_timeout_add_seconds(10, __dead_timeout_handler, GINT_TO_POINTER(pid));
-       return 0;
-}
-
-static int __listen_app_dead_signal(void *data)
-{
-       int ret;
-
-       ret = aul_listen_app_dead_signal(__app_dead_handler, data);
-       if (ret < 0)
-               return -1;
-
-       return 0;
-}
-
-static void __ignore_app_dead_signal(void)
-{
-       aul_listen_app_dead_signal(NULL, NULL);
-}
-
 static int __load_modules(const char *path)
 {
        DIR *dp;
@@ -358,12 +179,6 @@ static int __init(void)
                return -1;
        }
 
-       _signal_add_ready_cb(__listen_app_dead_signal, NULL);
-       _app_request_broker_set_disconnected_event_cb(__disconnected_event_cb,
-                       NULL);
-
-       restart_tbl = g_hash_table_new(g_str_hash, g_str_equal);
-
        r = _cynara_init();
        if (r != 0) {
                _E("cynara initialize failed.");
@@ -433,14 +248,6 @@ static void __finish(void)
        _app_lifecycle_fini();
        _request_fini();
        _cynara_finish();
-
-       if (restart_tbl) {
-               g_hash_table_destroy(restart_tbl);
-               restart_tbl = NULL;
-       }
-
-       __ignore_app_dead_signal();
-
        _appinfo_fini();
        _direct_launch_fini();
        _compinfo_fini();