Add poweroff stage to clarify poweroff sequence 94/227994/5
authorYoungjae Cho <y0.cho@samsung.com>
Wed, 18 Mar 2020 03:27:45 +0000 (12:27 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Wed, 18 Mar 2020 06:02:11 +0000 (15:02 +0900)
POWEROFF_DEFAULT
 - Default stage, poweroff has not been triggered
POWEROFF_TRIGGERED
 - Poweroff is triggered. Wait timer can be added up to this stage
POWEROFF_WAIT_OTHERS
 - Wait for other processes to clean up their resources

Change-Id: Iaf744a624c230a3d0ffc588aa60138264f184c72
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
src/power/power-handler.c

index d67103e..9f05cb5 100644 (file)
@@ -64,8 +64,6 @@
 static struct timeval tv_start_poweroff;
 static dd_list *poweroff_options;
 static struct power_option poweroff_opt;
-static bool poweroff_triggered;
-static bool poweroff_wait_timer_activated;
 static dd_list *poweroff_handles;
 
 static const char *poweroff_type_flagpaths[] = { // index denotes type
@@ -80,6 +78,14 @@ static const char *poweroff_type_names[] = { // index denotes type
        [POWEROFF_TYPE_EXIT] = POWER_EXIT,
 };
 
+enum poweroff_stage {
+       POWEROFF_DEFAULT,           /* Default stage, poweroff has not been triggered */
+       POWEROFF_TRIGGERED,         /* Poweroff is triggered. Wait timer can be added up to this stage */
+       POWEROFF_WAIT_OTHERS,       /* Wait for other processes to clean up their resources */
+};
+
+static enum poweroff_stage poweroff_stage;
+
 static const char *poweroff_type_to_name(enum poweroff_type type)
 {
        if (type <= 0 || type >= ARRAY_SIZE(poweroff_type_names))
@@ -322,38 +328,36 @@ static void poweroff_remove_handle(pid_t pid)
        free(handle);
 }
 
-static gboolean poweroff_timeout_cb(void *data)
+static gboolean poweroff_wait_timeout_cb(void *data)
 {
        char timeout[50] = {0,};
        pid_t pid = (pid_t)((intptr_t)data);
 
        poweroff_remove_handle(pid);
 
-       if (DD_LIST_LENGTH(poweroff_handles)) {
-               _D("Timer is left.");
-               return G_SOURCE_REMOVE;
-       }
-       _D("No timer left.");
+       /* All other processes finished cleanup. Poweroff is now on standby */
+       if (poweroff_stage == POWEROFF_WAIT_OTHERS && DD_LIST_LENGTH(poweroff_handles) == 0) {
+               _D("The last poweroff wait timer for pid %d is expired. Poweroff is now on standby.", pid);
 
-       if (!poweroff_type_to_name(poweroff_opt.type)) {
-               _E("Invalid type(%d).", poweroff_opt.type);
-               goto out;
-       }
+               CRITICAL_LOG("Starting poweroff sequence.");
 
-       // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure.
-       snprintf(timeout, sizeof(timeout), "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000);
-       sd_notify(0, timeout);
+               // Watchdog timeout 90 -> 30 sec to reduce delay from unexpected poweroff failure.
+               snprintf(timeout, sizeof(timeout), "WATCHDOG_USEC=%llu", (unsigned long long)POWEROFF_WAIT_SYSTEMD_MS*1000);
+               sd_notify(0, timeout);
 
-       make_power_flag(poweroff_opt.type, poweroff_opt.option);
+               make_power_flag(poweroff_opt.type, poweroff_opt.option);
 
-       if (disp_plgn.pm_lock_internal)
-               disp_plgn.pm_lock_internal(INTERNAL_LOCK_POWEROFF, LCD_OFF, STAY_CUR_STATE, 0);
+               if (disp_plgn.pm_lock_internal)
+                       disp_plgn.pm_lock_internal(INTERNAL_LOCK_POWEROFF, LCD_OFF, STAY_CUR_STATE, 0);
 
-       poweroff_prepare();
-       poweroff();
-out:
-       if (disp_plgn.update_pm_setting)
-               disp_plgn.update_pm_setting(SETTING_POWEROFF, poweroff_opt.type);
+               poweroff_prepare();
+               poweroff();
+
+               if (disp_plgn.update_pm_setting)
+                       disp_plgn.update_pm_setting(SETTING_POWEROFF, poweroff_opt.type);
+       } else {
+               _D("Poweroff wait timer for pid %d is expired, but keep waiting for others...", pid);
+       }
 
        return G_SOURCE_REMOVE;
 }
@@ -365,7 +369,7 @@ static gboolean poweroff_start_timers(void *data)
        bool timer_exist = false;
        int pid_alive = 0;
 
-       poweroff_wait_timer_activated = true;
+       poweroff_stage = POWEROFF_WAIT_OTHERS;
 
        DD_LIST_FOREACH(poweroff_handles, l, handle) {
                pid_alive = kill(handle->pid, 0);
@@ -377,7 +381,7 @@ static gboolean poweroff_start_timers(void *data)
                _D("Run timer, pid=%d timeout=%d timeout_id=%d.", handle->pid, handle->timeout, handle->timeout_id);
 
                handle->timeout_id = g_timeout_add_seconds(handle->timeout,
-                               poweroff_timeout_cb,
+                               poweroff_wait_timeout_cb,
                                (void *)((intptr_t)(handle->pid)));
 
                timer_exist = true;
@@ -397,7 +401,7 @@ static gboolean poweroff_start_timers(void *data)
                handle->pid = getpid();
                handle->timeout = 0;
                handle->timeout_id = g_timeout_add_seconds(handle->timeout,
-                               poweroff_timeout_cb,
+                               poweroff_wait_timeout_cb,
                                (void *)((intptr_t)(handle->pid)));
 
                if (!handle->timeout_id) {
@@ -475,8 +479,8 @@ static int power_execute_pid(const char *typename, const char *option)
 {
        int ret;
 
-       if (poweroff_triggered) {
-               _E("During poweroff.");
+       if (poweroff_stage >= POWEROFF_TRIGGERED) {
+               _E("Duplicate poweroff request. Poweroff was already triggered.");
                return -EINVAL;
        }
 
@@ -485,6 +489,7 @@ static int power_execute_pid(const char *typename, const char *option)
                _E("Failed to get type enum value(%d).", type_e);
                return -EINVAL;
        }
+
        if (poweroff_option_valid(type_e, option)) {
                poweroff_opt.type = type_e;
                free(poweroff_opt.option);
@@ -500,7 +505,7 @@ static int power_execute_pid(const char *typename, const char *option)
        if (ret < 0)
                _E("Failed to set vconf value for power off status: %d", vconf_get_ext_errno());
 
-       poweroff_triggered = true;
+       poweroff_stage = POWEROFF_TRIGGERED;
 
        /* Poweroff event broadcasting */
        system_shutdown_send_system_event();
@@ -550,6 +555,7 @@ static GVariant *dbus_power_handler(GDBusConnection *conn,
        if (ret < 0)
                goto out;
 
+
        CRITICAL_LOG("Poweroff PID(%d) requests %s.", ret, type_str);
        ret = power_execute_pid(type_str, NULL);
 
@@ -571,6 +577,7 @@ static GVariant *dbus_power_option_handler(GDBusConnection *conn,
        if (ret < 0)
                goto out;
 
+
        CRITICAL_LOG("Poweroff PID(%d) requests type=%s option=%s.", ret, type, option);
        ret = power_execute_pid(type, option);
 
@@ -580,6 +587,7 @@ out:
        return g_variant_new("(i)", ret);
 }
 
+/* timer can be added before the stage POWEROFF_WAIT_OTHERS */
 static GVariant *add_poweroff_time(GDBusConnection *conn,
        const gchar *sender, const gchar *path, const gchar *iface, const gchar *name,
        GVariant *param, GDBusMethodInvocation *invocation, gpointer user_data)
@@ -589,8 +597,8 @@ static GVariant *add_poweroff_time(GDBusConnection *conn,
        pid_t pid;
        dd_list *l;
 
-       if (poweroff_wait_timer_activated) {
-               _E("It's too late. Poweroff wait timers are already activated.");
+       if (poweroff_stage >= POWEROFF_WAIT_OTHERS) {
+               _E("It's too late. Poweroff is already in waiting stage.");
                ret = -1;
                goto out;
        }
@@ -601,7 +609,7 @@ static GVariant *add_poweroff_time(GDBusConnection *conn,
 
        pid = (pid_t)ret;
 
-       CRITICAL_LOG("PID %d request poweroff timer.", pid);
+       CRITICAL_LOG("PID %d requested to a poweroff timer.", pid);
 
        DD_LIST_FOREACH(poweroff_handles, l, handle) {
                if (handle->pid == pid)
@@ -647,7 +655,7 @@ static GVariant *remove_poweroff_time(GDBusConnection *conn,
 
        pid = (pid_t)ret;
 
-       _D("Remove_poweroff_timer pid=%d", pid);
+       CRITICAL_LOG("PID %d requested to remove poweroff timer.", pid);
 
        DD_LIST_FOREACH(poweroff_handles, l, handle) {
                if (handle->pid == pid)
@@ -655,15 +663,12 @@ static GVariant *remove_poweroff_time(GDBusConnection *conn,
        }
 
        if (handle) {
-               assert(handle);
-
-               if (handle && handle->timeout_id) {
+               if (handle->timeout_id)
                        g_source_remove(handle->timeout_id);
-                       handle->timeout = 0;
-                       handle->timeout_id = g_timeout_add_seconds(handle->timeout,
-                                       poweroff_timeout_cb,
-                                       (void *)((intptr_t)(handle->pid)));
-               }
+               handle->timeout = 0;
+               handle->timeout_id = g_timeout_add_seconds(handle->timeout,
+                               poweroff_wait_timeout_cb,
+                               (void *)((intptr_t)(handle->pid)));
        } else {
                _E("Invalid pid(%d).", pid);
                ret = -1;
@@ -772,6 +777,8 @@ static void power_init(void *data)
        ret = config_parse(POWER_CONF_FILE, load_config, NULL);
        if (ret < 0)
                _E("Failed to load power off config: %d", ret);
+
+       poweroff_stage = POWEROFF_DEFAULT;
 }
 
 static const struct device_ops power_device_ops = {