vip-process: rework vip-agent 41/263441/4 accepted/tizen/6.5/unified/20211028.115453 accepted/tizen/unified/20210914.084920 submit/tizen/20210913.042525 submit/tizen_6.5/20211028.162501 tizen_6.5.m2_release
authorYoungjae Cho <y0.cho@samsung.com>
Thu, 2 Sep 2021 07:39:39 +0000 (16:39 +0900)
committerYoungjae Cho <y0.cho@samsung.com>
Mon, 13 Sep 2021 03:00:08 +0000 (12:00 +0900)
vip-process now constructs vip configurations from each vip packages,
not from resourced itself. Each vip packages now define and install
vip configuration file at /etc/resourced/vip-process.d, and resourced
collects these configuration files. The format of new configuration
file is like below, and more option might be added in the future.

  [VIP_GROUP1]          // Section format: VIP_GROUP#
                           There can be multiple vip groups.
   If there is only one group, then just
   [VIP_GROUP] is possible.

  PROCESS=some_binary1 // Define vip processes.
  PROCESS=some_binary2
  ...

  SERVICE=some_unit1.service // Define vip services.
  SERVICE=some_unit2.service
  ...

  ACTION_ON_FAILURE=reboot  // Define action for the vip group.
                            // Currently only "reboot" is supported.

  [VIP_GROUP2]
  ...

Change-Id: I4d88f59a009a5a7800651a07f79ab37f2cfae719
Signed-off-by: Youngjae Cho <y0.cho@samsung.com>
CMakeLists.txt
packaging/resourced.spec
src/CMakeLists.txt
src/vip-agent/vip-process-iot-headless.conf [deleted file]
src/vip-agent/vip-process-tv.conf [deleted file]
src/vip-agent/vip-process.conf [deleted file]
src/vip-process/vip-process.c [moved from src/vip-agent/vip-process.c with 65% similarity]
src/vip-process/vip-process.h [moved from src/vip-agent/vip-process.h with 100% similarity]
src/vip-process/vip-release-agent.c [moved from src/vip-agent/vip-release-agent.c with 100% similarity]

index 81c6fc0..703ac01 100644 (file)
@@ -53,7 +53,7 @@ SET(FREEZER_SOURCE_DIR          ${SOURCE_DIR}/freezer)
 SET(HEART_SOURCE_DIR            ${SOURCE_DIR}/heart)
 SET(COMMON_SOURCE_DIR           ${SOURCE_DIR}/common)
 SET(CPU_SOURCE_DIR              ${SOURCE_DIR}/cpu)
-SET(VIP_SOURCE_DIR              ${SOURCE_DIR}/vip-agent)
+SET(VIP_SOURCE_DIR              ${SOURCE_DIR}/vip-process)
 SET(BLOCK_SOURCE_DIR            ${SOURCE_DIR}/block)
 SET(DEDUP_SOURCE_DIR            ${SOURCE_DIR}/dedup)
 
index 68b3f49..893cff9 100644 (file)
@@ -44,6 +44,7 @@ BuildRequires:  pkgconfig(storage)
 BuildRequires:  pkgconfig(libgum)
 BuildRequires:  pkgconfig(capi-system-device)
 BuildRequires:  pkgconfig(cmocka)
+BuildRequires:  pkgconfig(libsyscommon)
 
 Requires(post): %{_sbindir}/update-alternatives
 Requires(preun): %{_sbindir}/update-alternatives
@@ -156,7 +157,7 @@ mkdir -p %{buildroot}/%{confdir}/configs
 #   https://docs.fedoraproject.org/en-US/packaging-guidelines/Scriptlets/#ordering
 
 # List of configuration files provided by this package - update when any new config file is added!
-%define config_files block cpu cpu-sched heart memory proc swap vip-process dedup
+%define config_files block cpu cpu-sched heart memory proc swap dedup
 
 for i in %{confdir}/*.conf; do
        if [ "$i" = %{confdir}/"*.conf" ]; then
@@ -188,22 +189,18 @@ fi
 
 %post config-tv
 %{_sbindir}/update-alternatives --install %{confdir}/memory.conf resourced-config-memory %{confdir}/configs/config-memory-tv.conf 150
-%{_sbindir}/update-alternatives --install %{confdir}/vip-process.conf resourced-config-vip-process %{confdir}/configs/config-vip-process-tv.conf 150
 
 %preun config-tv
 if [ $1 -eq 0 ]; then
        %{_sbindir}/update-alternatives --remove resourced-config-memory %{confdir}/configs/config-memory-tv.conf
-       %{_sbindir}/update-alternatives --remove resourced-config-vip-process %{confdir}/configs/config-vip-process-tv.conf
 fi
 
 %post config-iot-headless
 %{_sbindir}/update-alternatives --install %{confdir}/memory.conf resourced-config-memory %{confdir}/configs/config-memory-iot-headless.conf 150
-%{_sbindir}/update-alternatives --install %{confdir}/vip-process.conf resourced-config-vip-process %{confdir}/configs/config-vip-process-iot-headless.conf 150
 
 %preun config-iot-headless
 if [ $1 -eq 0 ]; then
        %{_sbindir}/update-alternatives --remove resourced-config-memory %{confdir}/configs/config-memory-iot-headless.conf
-       %{_sbindir}/update-alternatives --remove resourced-config-vip-process %{confdir}/configs/config-vip-process-iot-headless.conf
 fi
 
 %files
@@ -232,7 +229,6 @@ fi
 %{confdir}/configs/config-proc.conf
 %{confdir}/configs/config-swap.conf
 %{confdir}/configs/config-dedup.conf
-%{confdir}/configs/config-vip-process.conf
 %{confdir}/configs/config-block.conf
 %{confdir}/configs/config-heart.conf
 %{confdir}/configs/config-cpu.conf
@@ -241,12 +237,10 @@ fi
 %files config-tv
 %manifest resourced.manifest
 %{confdir}/configs/config-memory-tv.conf
-%{confdir}/configs/config-vip-process-tv.conf
 
 %files config-iot-headless
 %manifest resourced.manifest
 %{confdir}/configs/config-memory-iot-headless.conf
-%{confdir}/configs/config-vip-process-iot-headless.conf
 
 %if %{?vip_agent_module} == ON
 %files vip-release-agent
index b8748f5..6c1e603 100644 (file)
@@ -82,6 +82,7 @@ SET(REQUIRES_LIST ${REQUIRES_LIST}
        capi-system-info
        libudev
        dbus-1
+       libsyscommon
   )
 
 INCLUDE(FindPkgConfig)
@@ -220,9 +221,6 @@ IF("${VIP_AGENT}" STREQUAL "ON")
   ADD_EXECUTABLE(vip-release-agent ${VIP_SOURCE_DIR}/vip-release-agent.c)
   TARGET_LINK_LIBRARIES(vip-release-agent resourced-private-api dlog)
   INSTALL(TARGETS vip-release-agent DESTINATION bin)
-  INSTALL(FILES ${VIP_SOURCE_DIR}/vip-process.conf DESTINATION ${RD_CONFIG_PATH})
-  INSTALL(FILES ${VIP_SOURCE_DIR}/vip-process-tv.conf DESTINATION ${RD_CONFIG_PATH})
-  INSTALL(FILES ${VIP_SOURCE_DIR}/vip-process-iot-headless.conf DESTINATION ${RD_CONFIG_PATH})
 ENDIF()
 
 INSTALL(FILES ${PROCESS_SOURCE_DIR}/proc.conf
diff --git a/src/vip-agent/vip-process-iot-headless.conf b/src/vip-agent/vip-process-iot-headless.conf
deleted file mode 100644 (file)
index 2623b06..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-[VIP_PROCESS]
-# VIP process list
-VIP_SYSTEMD_SERVICE=dbus.service
-VIP_SYSTEMD_SERVICE=ac.service
diff --git a/src/vip-agent/vip-process-tv.conf b/src/vip-agent/vip-process-tv.conf
deleted file mode 100644 (file)
index 8353929..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-[VIP_PROCESS]
-# VIP process list
-VIP_PROC_NAME=enlightenment
-VIP_SYSTEMD_SERVICE=ac.service
diff --git a/src/vip-agent/vip-process.conf b/src/vip-agent/vip-process.conf
deleted file mode 100644 (file)
index d4ce7ba..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-[VIP_PROCESS]
-# VIP process list
-#VIP_PROC_NAME=enlightenment
-VIP_SYSTEMD_SERVICE=dbus.service
-VIP_SYSTEMD_SERVICE=ac.service
similarity index 65%
rename from src/vip-agent/vip-process.c
rename to src/vip-process/vip-process.c
index aa8435b..acda0e3 100644 (file)
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
+#include <libsyscommon/list.h>
 
 #include "const.h"
 #include "resourced.h"
@@ -45,7 +46,8 @@
 #include "vip-process.h"
 #include "dbus-handler.h"
 
-#define VIP_CONF_FILE                  RD_CONFIG_FILE(vip-process)
+#define VIP_CONF_DIR                   "/etc/resourced/vip-process.d"
+#define VIP_CONF_SUFFIX                ".conf"
 
 #define SYSTEMD_DBUS_DEST              "org.freedesktop.systemd1"
 #define SYSTEMD_DBUS_UNIT_PATH         "/org/freedesktop/systemd1/unit/"
 
 #define BOOT_PARAM_VIP_DISABLED        "tizen.vip_reboot_disable"
 
-static char **arg_vip_proc_names = NULL;
-static char **arg_vip_systemd_services = NULL;
+struct vip_group {
+       char name[64];
+       GList *service;
+       GList *process;
+
+       /* options */
+       int reboot_on_failure;
+};
+
+static GList *vip_group_list;
 
 /* print log on console */
 static void vip_print_console(const char *format, ...)
@@ -193,30 +203,38 @@ static bool vip_check_all(void)
        int pid;
        int ret_val;
        bool ret = true;
-       char **pname = NULL;
-
-       FOREACH_STRV(pname, arg_vip_proc_names) {
-               pid = find_pid_from_cmdline(*pname);
-               if (pid < 0) {
-                       vip_print_console("[VIP FAILED] %s is not running", *pname);
-                       ret = false;
-               }
-       }
+       char *process;
+       char *service;
+       GList *elem1, *elem2;
+       struct vip_group *vg;
 
-       FOREACH_STRV(pname, arg_vip_systemd_services) {
-               ret_val = vip_get_service_mainpid(*pname, &pid);
-               if (ret_val < 0) {
-                       _E("Failed to get MainPID of service=%s", *pname);
+       SYS_G_LIST_FOREACH(vip_group_list, elem1, vg) {
+               if (!vg->reboot_on_failure)
                        continue;
+
+               SYS_G_LIST_FOREACH(vg->process, elem2, process) {
+                       pid = find_pid_from_cmdline(process);
+                       if (pid < 0) {
+                               vip_print_console("[VIP FAILED] %s is not running", process);
+                               ret = false;
+                       }
                }
 
-               /* The property MainPID can return a positive MainPID
-                * as a pid of inactive(dead) service if the service had once
-                * been active before. Therefore, it is necessary to check
-                * whether it is still alive. */
-               if (pid == 0 || kill(pid, 0) != 0) {
-                       vip_print_console("[VIP FAILED] %s is not running", *pname);
-                       ret = false;
+               SYS_G_LIST_FOREACH(vg->service, elem2, service) {
+                       ret_val = vip_get_service_mainpid(service, &pid);
+                       if (ret_val < 0) {
+                               _E("Failed to get MainPID of service=%s", service);
+                               continue;
+                       }
+
+                       /* The property MainPID can return a positive MainPID
+                        * as a pid of inactive(dead) service if the service had once
+                        * been active before. Therefore, it is necessary to check
+                        * whether it is still alive. */
+                       if (pid == 0 || kill(pid, 0) != 0) {
+                               vip_print_console("[VIP FAILED] %s is not running", service);
+                               ret = false;
+                       }
                }
        }
 
@@ -233,39 +251,42 @@ static void vip_force_reboot(void)
 
 static int vip_load_config(struct parse_result *result, void *user_data)
 {
-       char ***strv;
-       char **temp, **templist;
+       char vgname[64] = {0, };
+       struct vip_group *vg;
+       GList *elem;
 
-       if (strncmp(result->section, "VIP_PROCESS", sizeof("VIP_PROCESS") + 1)) {
-               _E("Invalid section name %s", result->section);
+       if (!user_data)
                return -1;
-       }
 
-       if (!result->name || !result->value) {
-               _E("lvalue or rvalue is empty");
+       if (!strstr(result->section, "VIP_GROUP"))
                return -1;
-       }
 
-       if (!strncmp(result->name, "VIP_PROC_NAME", sizeof("VIP_PROC_NAME") + 1))
-               strv = &arg_vip_proc_names;
-       else if (!strncmp(result->name, "VIP_SYSTEMD_SERVICE", sizeof("VIP_SYSTEMD_SERVICE") + 1))
-               strv = &arg_vip_systemd_services;
-       else {
-               _E("Invalid lvalue %s", result->name);
-               return -1;
+       snprintf(vgname, sizeof(vgname), "%s:%s", (char *)user_data, result->section);
+
+       SYS_G_LIST_FOREACH(vip_group_list, elem, vg) {
+               if (!strncmp(vg->name, vgname, sizeof(vg->name)))
+                       break;
        }
 
-       if (str_to_strv(result->value, &temp, WHITESPACE) < 0) {
-               _E("Failed to convert str to strv");
-               return -1;
+       if (!vg) {
+               vg = calloc(1, sizeof(struct vip_group));
+               if (!vg)
+                       return -1;
+               strncpy(vg->name, vgname, sizeof(vg->name));
+               SYS_G_LIST_APPEND(vip_group_list, vg);
        }
 
-       if (strv_attach(*strv, temp, &templist, true) < 0) {
-               _E("Failed to add %s to VIP list", result->value);
-               return -1;
+       if (!strncmp(result->name, "PROCESS", sizeof("PROCESS"))) {
+               SYS_G_LIST_APPEND(vg->process, strndup(result->value, PATH_MAX));
+       } else if (!strncmp(result->name, "SERVICE", sizeof("SERVICE"))) {
+               SYS_G_LIST_APPEND(vg->service, strndup(result->value, PATH_MAX));
+       } else if (!strncmp(result->name, "ACTION_ON_FAILURE", sizeof("ACTION_ON_FAILURE"))) {
+               if (!strncmp(result->value, "reboot", sizeof("reboot")))
+                       vg->reboot_on_failure = 1;
+               else
+                       vg->reboot_on_failure = 0;
        }
 
-       *strv = templist;
        return 0;
 }
 
@@ -310,46 +331,53 @@ static int vip_create_sub_cgroup(const char *name, pid_t pid)
 
 static void vip_create_proc_name_groups(void)
 {
-       char **pname = NULL;
+       GList *elem1, *elem2;
+       struct vip_group *vg;
+       char *process;
        int r;
 
-       if (!arg_vip_proc_names)
-               return;
+       SYS_G_LIST_FOREACH(vip_group_list, elem1, vg) {
+               if (!vg->reboot_on_failure)
+                       continue;
 
-       FOREACH_STRV(pname, arg_vip_proc_names) {
-               pid_t pid = 0;
-
-               pid = find_pid_from_cmdline(*pname);
-               if (pid > 0) {
-                       r = vip_create_sub_cgroup(*pname, pid);
-                       if (r < 0)
-                               _E("failed to create "
-                                  "sub cgroup of '%s', ignoring", *pname);
-               } else
-                       _D("failed to find pid of name: %s", *pname);
+               SYS_G_LIST_FOREACH(vg->process, elem2, process) {
+                       pid_t pid = 0;
+
+                       pid = find_pid_from_cmdline(process);
+                       if (pid > 0) {
+                               r = vip_create_sub_cgroup(process, pid);
+                               if (r < 0)
+                                       _E("failed to create sub cgroup of '%s', ignoring", process);
+                       } else {
+                               _D("failed to find pid of name: %s", process);
+                       }
+               }
        }
 }
 
 static void vip_create_systemd_service_groups(void)
 {
-       char **pname = NULL;
+       GList *elem1, *elem2;
+       struct vip_group *vg;
+       char *service;
 
-       if (!arg_vip_systemd_services)
-               return;
+       SYS_G_LIST_FOREACH(vip_group_list, elem1, vg) {
+               if (!vg->reboot_on_failure)
+                       continue;
 
-       FOREACH_STRV(pname, arg_vip_systemd_services) {
-               int ret_val;
-               pid_t pid;
+               SYS_G_LIST_FOREACH(vg->service, elem2, service) {
+                       int ret_val;
+                       pid_t pid;
 
-               ret_val = vip_get_service_mainpid(*pname, &pid);
-               if (ret_val == -ECOMM)
-                       continue;
+                       ret_val = vip_get_service_mainpid(service, &pid);
+                       if (ret_val == -ECOMM)
+                               continue;
 
-               if (pid > 0) {
-                       ret_val = vip_create_sub_cgroup(*pname, pid);
-                       if (ret_val < 0)
-                               _E("failed to create "
-                                  "sub cgroup of '%s', ignoring", *pname);
+                       if (pid > 0) {
+                               ret_val = vip_create_sub_cgroup(service, pid);
+                               if (ret_val < 0)
+                                       _E("failed to create sub cgroup of '%s', ignoring", service);
+                       }
                }
        }
 }
@@ -377,6 +405,44 @@ static int vip_process_disable(void *data)
        return 0;
 }
 
+static void vip_load_configs(void)
+{
+       DIR *dirp;
+       struct dirent *ent;
+
+       if ((dirp = opendir(VIP_CONF_DIR)) == NULL) {
+               _E("Failed to open %s, %m", VIP_CONF_DIR);
+               return;
+       }
+
+       while ((ent = readdir(dirp))) {
+               char path[PATH_MAX] = {0, };
+
+               if (!strstr(ent->d_name, VIP_CONF_SUFFIX))
+                       continue;
+
+               snprintf(path, sizeof(path), "%s/%s", VIP_CONF_DIR, ent->d_name);
+
+               config_parse(path, vip_load_config, (void *)ent->d_name);
+       }
+
+       closedir(dirp);
+
+       /* print result */
+       GList *elem1, *elem2;
+       struct vip_group *vg;
+       char *name;
+
+       SYS_G_LIST_FOREACH(vip_group_list, elem1, vg) {
+               _D("%s", vg->name);
+               _D(" reboot on failure=%d", vg->reboot_on_failure);
+               SYS_G_LIST_FOREACH(vg->process, elem2, name)
+                       _D(" vip process: %s", name);
+               SYS_G_LIST_FOREACH(vg->service, elem2, name)
+                       _D(" vip service: %s", name);
+       }
+}
+
 static int resourced_vip_process_init(void *data)
 {
        _cleanup_close_ int checkfd = -1;
@@ -394,14 +460,7 @@ static int resourced_vip_process_init(void *data)
                        _E("failed to remove %s: %m", CHECK_RELEASE_PROGRESS);
        }
 
-       r = config_parse(VIP_CONF_FILE, vip_load_config, NULL);
-       if (r < 0) {
-               _E("failed to parse vip config file: %m");
-               return RESOURCED_ERROR_FAIL;
-       }
-
-       if (!arg_vip_proc_names)
-               return RESOURCED_ERROR_NONE;
+       vip_load_configs();
 
        if (!is_mounted(VIP_CGROUP)) {
                r = cgroup_make_subdir(DEFAULT_CGROUP, "vip", NULL);
@@ -442,11 +501,27 @@ static int resourced_vip_process_init(void *data)
 
 static int resourced_vip_process_finalize(void *data)
 {
+       GList *elem1, *elem1_n, *elem2, *elem2_n;
+       struct vip_group *vg;
+       char *process, *service;
+
        if (vip_boot_param_reboot_disabled())
                return RESOURCED_ERROR_NONE;
 
-       strv_free_full(&arg_vip_proc_names);
-       strv_free_full(&arg_vip_systemd_services);
+       SYS_G_LIST_FOREACH_SAFE(vip_group_list, elem1, elem1_n, vg) {
+               SYS_G_LIST_FOREACH_SAFE(vg->process, elem2, elem2_n, process) {
+                       SYS_G_LIST_REMOVE(vg->process, process);
+                       free(process);
+               }
+
+               SYS_G_LIST_FOREACH_SAFE(vg->service, elem2, elem2_n, service) {
+                       SYS_G_LIST_REMOVE(vg->service, service);
+                       free(service);
+               }
+
+               SYS_G_LIST_REMOVE(vip_group_list, vg);
+               free(vg);
+       }
 
        vip_process_disable(NULL);
        unregister_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, vip_booting_done);