Handle zombie alarm 32/214132/3
authorInkyun Kil <inkyun.kil@samsung.com>
Wed, 18 Sep 2019 08:31:31 +0000 (17:31 +0900)
committerInkyun Kil <inkyun.kil@samsung.com>
Wed, 18 Sep 2019 09:36:28 +0000 (18:36 +0900)
 - If G_DBUS_ERROR_SERVICE_UNKNOWN error occurs, exclude it from alarm
 schedule list.

Change-Id: I6d68207282e3d6f9e44c11c44c3f9ef3bc101d81
Signed-off-by: Inkyun Kil <inkyun.kil@samsung.com>
include/alarm-internal.h
server/alarm-manager-dbus.c
server/alarm-manager-schedule.c

index 8744ce3..d8959ff 100644 (file)
@@ -126,6 +126,7 @@ typedef struct {
        long requested_interval;
        int is_ref;
        bool global;
+       bool zombie_mode;
 } __alarm_info_t;
 
 typedef struct {
index 0da088a..b12bd9f 100644 (file)
 extern __alarm_server_context_t alarm_context;
 extern GSList *g_expired_alarm_list;
 
+struct watch_info_t {
+       int watch_id;
+       alarm_id_t alarm_id;
+};
+
 static GDBusNodeInfo *introspection_data;
 static const gchar introspection_xml[] =
 "<node name='/org/tizen/alarm/manager'>"
@@ -288,11 +293,118 @@ static gboolean __send_noti_to_session_bus(char *service_name,
        return TRUE;
 }
 
+static void __on_name_appeared(GDBusConnection *connection,
+               const gchar     *name,
+               const gchar     *name_owner,
+               gpointer         user_data)
+{
+       SECURE_LOGW("alarm sender name appeared : %s  %s", name, name_owner);
+
+       struct watch_info_t *watch_info = (struct watch_info_t *)user_data;
+       GSList *gs_iter;
+       __alarm_info_t *entry;
+       alarm_id_t alarm_id = watch_info->alarm_id;
+
+       g_bus_unwatch_name(watch_info->watch_id);
+       free(watch_info);
+
+       for (gs_iter = alarm_context.alarms; gs_iter != NULL; gs_iter = g_slist_next(gs_iter)) {
+               entry = gs_iter->data;
+               if (alarm_id == entry->alarm_id) {
+                       entry->zombie_mode = false;
+
+                       _alarm_disable_timer(alarm_context);
+                       _clear_scheduled_alarm_list();
+                       _alarm_schedule();
+                       _rtc_set();
+
+                       return;
+               }
+       }
+}
+
+static void __alarm_send_noti_to_application_reply(
+               GObject *source_object, GAsyncResult *res, gpointer user_data) {
+
+       GVariant *message;
+       GDBusConnection *conn;
+       GError *error = NULL;
+       alarm_id_t *reply_alarm_id = (alarm_id_t *)user_data;
+       char *service_name = NULL;
+       char *app_unique_name = NULL;
+       struct watch_info_t *watch_info;
+       char log_message[ALARMMGR_LOG_MESSAGE_SIZE] = {0,};
+
+       GSList *gs_iter;
+       __alarm_info_t *entry;
+       bool is_existed = false;
+
+       conn = G_DBUS_CONNECTION(source_object);
+       message = g_dbus_connection_call_finish(conn, res, &error);
+
+       if (error != NULL && error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) {
+               for (gs_iter = alarm_context.alarms; gs_iter != NULL; gs_iter = g_slist_next(gs_iter) ) {
+                       entry = gs_iter->data;
+
+                       if (*reply_alarm_id == entry->alarm_id) {
+                               is_existed = true;
+
+                               app_unique_name =  entry->app_unique_name;
+
+                               if (entry->dst_service_name == NULL)
+                                       service_name = entry->app_service_name_mod;
+                               else
+                                       service_name = entry->dst_service_name_mod;
+
+                               break;
+                       }
+               }
+
+
+               LOGW("failed to send alarm expired noti [%d: %s] [id : %d, %s -> %s]",
+                               error->code, error->message, *reply_alarm_id,
+                               app_unique_name, service_name);
+
+               snprintf(log_message, sizeof(log_message),
+                               "failed to send alarm expired noti [%d: %s] [id : %d, %s -> %s]",
+                               error->code, error->message, *reply_alarm_id, app_unique_name, service_name);
+               _save_module_log("EXPIRED_FAIL", log_message);
+
+               g_error_free(error);
+
+               if (is_existed) {
+                       entry->zombie_mode = true;
+                       watch_info = (struct watch_info_t *)calloc(1, sizeof(struct watch_info_t));
+                       watch_info->alarm_id = entry->alarm_id;
+                       watch_info->watch_id = g_bus_watch_name_on_connection(
+                                       alarm_context.connection,
+                                       service_name,
+                                       G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                       __on_name_appeared,
+                                       NULL,
+                                       watch_info,
+                                       NULL);
+
+                       alarm_context.c_due_time = -1;
+                       _alarm_disable_timer(alarm_context);
+                       _clear_scheduled_alarm_list();
+                       _alarm_schedule();
+                       _rtc_set();
+               }
+       } else {
+               g_variant_unref(message);
+       }
+
+       free(reply_alarm_id);
+
+}
+
 void _alarm_send_noti_to_application_by_dbus(const char *app_service_name,
                alarm_id_t alarm_id, int msec, uid_t uid)
 {
        char service_name[MAX_SERVICE_NAME_LEN] = {0,};
        gboolean ret;
+       alarm_id_t *reply_alarm_id;
 
        if (app_service_name == NULL || strlen(app_service_name) == 0) {
                LOGE("This alarm destination is invalid.");
@@ -312,6 +424,8 @@ void _alarm_send_noti_to_application_by_dbus(const char *app_service_name,
                        LOGE("failed to send alarm expired noti for %d, %s",
                                        alarm_id, service_name);
        } else {
+               reply_alarm_id = (alarm_id_t *)calloc(1, sizeof(alarm_id_t));
+               *reply_alarm_id = alarm_id;
                g_dbus_connection_call(alarm_context.connection,
                                service_name,
                                "/org/tizen/alarm/client",
@@ -322,8 +436,8 @@ void _alarm_send_noti_to_application_by_dbus(const char *app_service_name,
                                G_DBUS_CALL_FLAGS_NONE,
                                -1,
                                NULL,
-                               NULL,
-                               NULL);
+                               __alarm_send_noti_to_application_reply,
+                               reply_alarm_id);
        }
 }
 
index a353e00..68b9180 100644 (file)
@@ -470,8 +470,10 @@ static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time)
 
                double interval = 0;
 
-               SECURE_LOGD("alarm[%d] with duetime(%ld) at current(%ld)\n",
-                               entry->alarm_id, due_time, current_time);
+               SECURE_LOGD("alarm[%d] with duetime(%ld) at current(%ld) - (%s) z:%d",
+                               entry->alarm_id, due_time, current_time,
+                               entry->app_unique_name, (int)entry->zombie_mode);
+
                if (due_time == 0)      /*0 means this alarm has been disabled*/ {
                        continue;
                }
@@ -479,7 +481,8 @@ static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time)
                interval = difftime(due_time, current_time);
 
                if (interval < 0)       /*When the alarm expires, it may makes an error.*/ {
-                       LOGW("The duetime of alarm(%d) is OVER.", entry->alarm_id);
+                       LOGW("The duetime of alarm(%d) is OVER.(z:%d)",
+                                       entry->alarm_id, entry->zombie_mode);
 
                        _alarm_set_next_duetime(entry);
                        if (entry->due_time < current_time) {
@@ -501,6 +504,9 @@ static bool __find_next_alarm_to_be_scheduled(time_t *min_due_time)
 
                }
 
+               if (entry->zombie_mode)
+                       continue;
+
                interval = difftime(due_time, min_time);
 
                if ((interval < 0) || min_time == -1)
@@ -528,7 +534,7 @@ void _alarm_schedule()
                        entry = (__alarm_info_t *)iter->data;
                        due_time = entry->due_time;
 
-                       if (due_time == min_time)
+                       if (due_time == min_time && entry->zombie_mode == false)
                                _add_to_scheduled_alarm_list(entry);
                }