diff options
author | Inkyun Kil <inkyun.kil@samsung.com> | 2019-09-18 17:31:31 +0900 |
---|---|---|
committer | Inkyun Kil <inkyun.kil@samsung.com> | 2019-09-18 18:36:28 +0900 |
commit | 2a114905a9f7fb31701214942fbe9c1fe27d6df6 (patch) | |
tree | dd3781f809e80da4bf45444ba39d84b4ff1ceda1 | |
parent | 990babc93119b3f5551bc591f82836b262e5cac9 (diff) | |
download | alarm-manager-2a114905a9f7fb31701214942fbe9c1fe27d6df6.tar.gz alarm-manager-2a114905a9f7fb31701214942fbe9c1fe27d6df6.tar.bz2 alarm-manager-2a114905a9f7fb31701214942fbe9c1fe27d6df6.zip |
Handle zombie alarm
- 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>
-rw-r--r-- | include/alarm-internal.h | 1 | ||||
-rw-r--r-- | server/alarm-manager-dbus.c | 118 | ||||
-rw-r--r-- | server/alarm-manager-schedule.c | 14 |
3 files changed, 127 insertions, 6 deletions
diff --git a/include/alarm-internal.h b/include/alarm-internal.h index 8744ce3..d8959ff 100644 --- a/include/alarm-internal.h +++ b/include/alarm-internal.h @@ -126,6 +126,7 @@ typedef struct { long requested_interval; int is_ref; bool global; + bool zombie_mode; } __alarm_info_t; typedef struct { diff --git a/server/alarm-manager-dbus.c b/server/alarm-manager-dbus.c index 0da088a..b12bd9f 100644 --- a/server/alarm-manager-dbus.c +++ b/server/alarm-manager-dbus.c @@ -33,6 +33,11 @@ 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); } } diff --git a/server/alarm-manager-schedule.c b/server/alarm-manager-schedule.c index a353e00..68b9180 100644 --- a/server/alarm-manager-schedule.c +++ b/server/alarm-manager-schedule.c @@ -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); } |