BuildRequires: pkgconfig(libgum)
BuildRequires: pkgconfig(capi-system-device)
BuildRequires: pkgconfig(cmocka)
+BuildRequires: pkgconfig(libsyscommon)
Requires(post): %{_sbindir}/update-alternatives
Requires(preun): %{_sbindir}/update-alternatives
# 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
%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
%{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
%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
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <libsyscommon/list.h>
#include "const.h"
#include "resourced.h"
#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, ...)
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;
+ }
}
}
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;
}
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);
+ }
}
}
}
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;
_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);
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);