Check the stat file again to make sure it's cpu busy 33/287933/25
authorYoungHun Kim <yh8004.kim@samsung.com>
Wed, 8 Feb 2023 02:12:24 +0000 (11:12 +0900)
committerYoungHun Kim <yh8004.kim@samsung.com>
Mon, 13 Feb 2023 06:46:38 +0000 (15:46 +0900)
 - CPU utilization, as some tools like pcup may not be actively maintained or may not be accurate on modern systems.
 - The top, mpstat, sar, and htop commands are commonly used to monitor CPU usage on Linux systems.
 - So I have updated to check again the /proc/stat periodically after new timer creation considering performance

Change-Id: If76612dec2ed201abe617bbf4c7fd192a979f2f0

packaging/mused.spec
server/include/muse_server_system.h
server/src/muse_server_private.c
server/src/muse_server_system.c

index 2c817ea..9e798c0 100644 (file)
@@ -1,6 +1,6 @@
 Name:       mused
 Summary:    A multimedia daemon
-Version:    0.3.161
+Version:    0.3.162
 Release:    0
 Group:      System/Libraries
 License:    Apache-2.0
index bb55417..13fb39b 100644 (file)
@@ -40,15 +40,28 @@ extern "C" {
 #define MS_DBUS_INTERFACE                      "org.freedesktop.DBus"
 #define MS_DBUS_PATH                           "/org/freedesktop/DBus"
 
+typedef struct ms_cpu_jiffies {
+       unsigned long long user;
+       unsigned long long nice;
+       unsigned long long system;
+       unsigned long long idle;
+       guint id;
+       int counter;
+       int usage;
+} ms_cpu_jiffies_t;
+
 typedef struct ms_system {
        GDBusConnection *connection;
        GHashTable *platform_info_table;
        GMutex lock;
        int muse_poweroff_id;
        int muse_rm_id;
+       ms_cpu_jiffies_t st;
 } ms_system_t;
 
 void ms_system_init(ms_system_t *system);
+void ms_system_stat_attach(ms_system_t *system);
+void ms_system_stat_detach(ms_system_t *system);
 void ms_system_deinit(ms_system_t *system);
 gboolean ms_system_get_gdbus(GDBusConnection **connection);
 void ms_system_subscribe_external_event(ms_system_t *system);
index ed508db..ae22021 100644 (file)
@@ -80,7 +80,7 @@ static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition conditio
 static void _ms_wait_event(void);
 static void _ms_diag_init(void);
 static void _ms_diag_deinit(void);
-static gboolean _ms_idle_cb(gpointer user_data);
+static gboolean _ms_idle_cb(gpointer data);
 static int _ms_open_lockfile(void);
 
 static void _ms_wait_event(void)
@@ -266,6 +266,7 @@ static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition conditio
        muse_module_h candidate_m = NULL;
        intptr_t module_addr = 0;
        GQueue *instance_queue = NULL;
+       ms_system_t *system = NULL;
        ms_connection_t *connection = NULL;
        char time_buf[MUSE_MSG_TIME_LEN];
 
@@ -275,6 +276,11 @@ static gboolean _ms_connection_handler(GIOChannel *source, GIOCondition conditio
 
        muse_return_val_if_fail(muse_server, FALSE);
 
+       system = muse_server->system;
+       muse_return_val_if_fail(system, FALSE);
+
+       ms_system_stat_detach(system);
+
        connection = muse_server->connection;
        muse_return_val_if_fail(connection, FALSE);
 
@@ -582,7 +588,7 @@ static void _ms_diag_deinit(void)
        d->msg_aq = NULL;
 }
 
-static gboolean _ms_idle_cb(gpointer user_data)
+static gboolean _ms_idle_cb(gpointer data)
 {
        struct timespec tv;
        char time_buf[MUSE_MSG_TIME_LEN];
@@ -1114,12 +1120,16 @@ void ms_check_cpu_memory(void)
        int used_pss, memory_threshold, cpu_usage, cpu_threshold;
        char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
        ms_connection_t *connection = NULL;
+       ms_system_t *system = NULL;
 
        muse_return_if_fail(muse_server);
 
        connection = muse_server->connection;
        muse_return_if_fail(connection);
 
+       system = muse_server->system;
+       muse_return_if_fail(system);
+
        ms_connection_lock(connection);
 
        if (g_queue_is_empty(connection->instance_q) && ms_is_server_ready()) {
@@ -1131,17 +1141,19 @@ void ms_check_cpu_memory(void)
                memory_threshold = ms_config_get_memory_threshold();
                cpu_threshold = ms_config_get_cpu_threshold();
 
-               if (used_pss >= memory_threshold || cpu_usage >= cpu_threshold) {
+               if (used_pss >= memory_threshold) {
                        ms_log_process_info(muse_server->pid);
 
-                       snprintf(err_msg, sizeof(err_msg), "[Memory Leak] %d >= %d (KByte) [CPU] %d >= %d %%",
-                               used_pss, memory_threshold, cpu_usage, cpu_threshold);
+                       snprintf(err_msg, sizeof(err_msg), "[Memory Leak] %d >= %d (KByte)", used_pss, memory_threshold);
 
                        LOGE("%s", err_msg);
                        ms_connection_unlock(connection);
                        ms_terminate(SIGTERM);
                }
 
+               if (cpu_usage > cpu_threshold)
+                       ms_system_stat_attach(system);
+
                muse_core_remove_all_fd_table();
        } else {
                LOGI("skip cpu memory check due to instance queue length : %d", g_queue_get_length(connection->instance_q));
index 8e5b10a..e368c19 100644 (file)
@@ -27,6 +27,9 @@
 
 #define MUSE_STORAGE_EXTERNAL_FEATURE          "http://tizen.org/feature/storage.external"
 
+#define MUSE_STAT_CHECK_COUNT                          3
+#define MUSE_STAT_TIMER_PERIOD                         1
+
 enum muse_poweroff_type {
        MUSE_POWER_OFF_NONE = 0,
        MUSE_POWER_OFF_POPUP,
@@ -55,6 +58,9 @@ static void _ms_resource_manager_owner_name_changed_cb(GDBusConnection *con, con
                        const gchar *interface_name, const gchar *signal_name, GVariant *parameters, gpointer user_data);
 #endif
 
+static void _ms_system_stat_reset_cb(gpointer user_data);
+static gboolean _ms_system_cpu_usage_cb(gpointer user_data);
+
 #ifdef MUSE_USE_POWER_OFF_STATE_CHANGE
 static int _ms_system_subscribe_poweroff_state_change(ms_system_t *system)
 {
@@ -288,6 +294,64 @@ out:
 }
 #endif
 
+static void _ms_system_stat_reset_cb(gpointer user_data)
+{
+       ms_system_t *system = (ms_system_t *)user_data;
+
+       muse_return_if_fail(system);
+
+       LOGI("memset stat id %u", system->st.id);
+       memset(&system->st, 0, sizeof(ms_cpu_jiffies_t));
+}
+
+static gboolean _ms_system_cpu_usage_cb(gpointer user_data)
+{
+       FILE *fp;
+       char buf[MUSE_MSG_LEN_MAX];
+       char err_msg[MUSE_MSG_LEN_MAX] = {'\0',};
+       unsigned long long u, n, s, i;
+       ms_system_t *system = (ms_system_t *)user_data;
+       int cpu_threshold = ms_config_get_cpu_threshold();
+
+       fp = fopen("/proc/stat", "r");
+       if (!fp)
+               return G_SOURCE_REMOVE;
+       fgets(buf, sizeof(buf), fp);
+       fclose(fp);
+
+       sscanf(buf, "cpu %llu %llu %llu %llu", &u, &n, &s, &i);
+
+       u -= system->st.user;
+       n -= system->st.nice;
+       s -= system->st.system;
+       i -= system->st.idle;
+
+       system->st.user += u;
+       system->st.nice += n;
+       system->st.system += s;
+       system->st.idle += i;
+
+       system->st.usage = (int)100 * (u + n + s) / (u + n + s + i);
+       LOGD("[#%d] cpu usage %d %%", system->st.counter, system->st.usage);
+
+       if (system->st.usage < cpu_threshold)
+               return G_SOURCE_REMOVE;
+
+       system->st.counter++;
+
+       if (system->st.counter >= MUSE_STAT_CHECK_COUNT) {
+               ms_log_process_info(ms_get_instance()->pid);
+
+               snprintf(err_msg, sizeof(err_msg), "[CPU BUSY] %d >= %d %%", system->st.usage, cpu_threshold);
+
+               LOGE("%s", err_msg);
+               ms_terminate(SIGTERM);
+               return G_SOURCE_REMOVE;
+       }
+
+       return G_SOURCE_CONTINUE;
+}
+
 void ms_system_init(ms_system_t *system)
 {
        GError *error = NULL;
@@ -312,6 +376,33 @@ void ms_system_init(ms_system_t *system)
        LOGD("Leave");
 }
 
+void ms_system_stat_attach(ms_system_t *system)
+{
+       muse_return_if_fail(system);
+       muse_return_if_fail(system->st.id == 0);
+
+       system->st.id = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
+                                               MUSE_STAT_TIMER_PERIOD,
+                                               _ms_system_cpu_usage_cb,
+                                               (gpointer)system,
+                                               _ms_system_stat_reset_cb);
+
+       LOGI("add stat id %u", system->st.id);
+}
+
+void ms_system_stat_detach(ms_system_t *system)
+{
+       muse_return_if_fail(system);
+
+       LOGI("remove stat id %u", system->st.id);
+
+       if (system->st.id == 0)
+               return;
+
+       if (!g_source_remove(system->st.id))
+               LOGE("Failed to remove %u", system->st.id);
+}
+
 void ms_system_deinit(ms_system_t *system)
 {
        muse_return_if_fail(system);