appid_len = strlen(appid);
pkgname_len = strlen(pkgname);
- if (appid_len >= MAX_APPID_LENGTH - 1 ||
- pkgname_len >= MAX_PKGNAME_LENGTH - 1) {
+ if (appid_len >= sizeof ai->appid - 1 ||
+ pkgname_len >= sizeof ai->pkgname - 1) {
_E("appid length = %d, pkgname length = %d",
appid_len, pkgname_len);
return NULL;
}
/* appid and pkgname are terminated with null */
- strncpy(ai->appid, appid, appid_len);
- ai->appid[appid_len] = '\0';
- strncpy(ai->pkgname, pkgname, pkgname_len);
- ai->pkgname[pkgname_len] = '\0';
+ strncpy(ai->appid, appid, sizeof ai->appid);
+ ai->appid[sizeof ai->appid - 1] = '\0';
+ strncpy(ai->pkgname, pkgname, sizeof ai->pkgname);
+ ai->pkgname[sizeof ai->pkgname - 1] = '\0';
ai->ref = 0;
g_rw_lock_writer_lock(&resourced_appinfo_lock);
cgroup_exists = cgroup_is_exists(buf);
if (!cgroup_exists) {
+ /* FIXME: do something about this mounting, then replace
+ * `is_exists` with checking for -EEXIST in `create`,
+ * as currently this is both duplication AND a race condition */
if (!strncmp(parentdir, DEFAULT_CGROUP, sizeof(DEFAULT_CGROUP))) {
ret = mount("tmpfs", DEFAULT_CGROUP, "tmpfs",
MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, "mode=755");
lineno++;
start = line;
- start[strcspn(start, NEWLINE)] = '\0';
+ truncate_nl(start);
start = trim_str(start);
if (*start == COMMENT) {
int modules_add_methods(void)
{
- d_bus_register_methods(RESOURCED_DBUS_OBJECT_PATH, resourced_module_methods_xml,
+ return d_bus_register_methods(RESOURCED_DBUS_OBJECT_PATH, resourced_module_methods_xml,
resourced_module_methods, ARRAY_SIZE(resourced_module_methods));
- return 0;
}
if (r < 0)
return -ENOMEM;
- r = access(path, F_OK);
- if (r < 0)
- return -errno;
-
f = fopen(path, "re");
if (!f)
return -errno;
if (!argv)
return RESOURCED_ERROR_INVALID_PARAMETER;
+ /* execve already checks for existence (duplication + race condition),
+ * but would make it much harder to return a failure to the caller */
if (access(argv[0], F_OK)) {
_E("There is no %s", argv[0]);
return RESOURCED_ERROR_INVALID_PARAMETER;
if (fork() == 0) {
fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644);
if (fd < 0) {
- _E("Failed to create/open file %s", filename);
+ _E("Failed to create/open file \"%s\": %m", filename);
+ return RESOURCED_ERROR_FAIL;
+ }
+ if (dup2(fd, 1) < 0) {
+ _E("Failed to duplicate a file descriptor: %m");
+ close(fd);
return RESOURCED_ERROR_FAIL;
}
- dup2(fd, 1);
status = execvp(argv[0], argv);
close(fd);
}
return 0;
}
-void strv_free_full(char **strv)
+void strv_free_full(char ***strv)
{
char **s;
- if (!strv)
+ if (!strv || !*strv)
return;
- FOREACH_STRV(s, strv) {
- if (s && *s) {
- free(*s);
- *s = NULL;
- }
+ FOREACH_STRV(s, *strv) {
+ free(*s);
+ *s = NULL;
}
- free(strv);
- strv = NULL;
+ free(*strv);
+ *strv = NULL;
}
int str_to_strv(const char *str, char ***strv, const char *seperator);
size_t sizeof_strv(const char **strv);
int strv_attach(char **first, char **second, char ***strv, bool free_second);
-void strv_free_full(char **strv);
+void strv_free_full(char ***strv);
#endif /*_RESOURCED_UTIL_H_*/
static int cpu_widget_state(void *data)
{
struct proc_status *ps = (struct proc_status *)data;
- assert(ps && ps->pai);
+ assert(ps);
+ assert(ps->pai);
_D("widget background: pid = %d, appname = %s", ps->pid, ps->pai->appid);
- if (ps->pai && CHECK_BIT(ps->pai->flags, PROC_DOWNLOADAPP))
+ if (CHECK_BIT(ps->pai->flags, PROC_DOWNLOADAPP))
cpu_move_cgroup(ps->pid, CPU_BACKGROUND_GROUP);
return RESOURCED_ERROR_NONE;
}
{
_D("decision memory init finished");
- logging_register_listener("memory", decision_memory_updated_cb);
+ logging_register_listener(MEM_NAME, decision_memory_updated_cb);
decision_module_register(&decision_memory);
return RESOURCED_ERROR_NONE;
_D("decision memory finalize");
decision_module_unregister(&decision_memory);
- logging_unregister_listener(DECISION_MEMORY,
- decision_memory_updated_cb);
+ logging_unregister_listener(MEM_NAME, decision_memory_updated_cb);
return RESOURCED_ERROR_NONE;
}
struct heart_abnormal_table *table = NULL;
GHashTable *list = (GHashTable *)data;
- sscanf((char *)entry->data, "%*s %*s %u ", &type);
+ if (sscanf((char *)entry->data, "%*s %*s %u ", &type) < 0) {
+ _E("sscanf failed, %m");
+ return;
+ }
+
if (type >= ABNORMAL_TYPE_MAX) {
_E("wrong abnormal type, %u", type);
return;
return BATTERY_DISCHARGE_AVG;
}
-static int heart_battery_save_used_time(char *key, struct battery_used *used)
+static void heart_battery_save_used_time(char *key, struct battery_used *used)
{
- if (!key || !used)
- return RESOURCED_ERROR_FAIL;
+ assert(key);
+ assert(used);
logging_leveldb_putv(key, strlen(key), "%d %d ",
used->used_time_sec, used->last_update_time);
- return RESOURCED_ERROR_NONE;
};
-static int heart_battery_save_status(char *key, struct battery_status *status)
+static void heart_battery_save_status(char *key, struct battery_status *status)
{
- if (!key || !status)
- return RESOURCED_ERROR_FAIL;
+ assert(key);
+ assert(status);
logging_leveldb_putv(key, strlen(key), "%d %ld %ld %ld %ld %d %d ",
status->curr_capacity,
status->curr_cap_counter[CHARGING],
status->curr_charger_status,
status->reset_mark);
-
- return RESOURCED_ERROR_NONE;
};
-static int heart_battery_save_usage(char *key, struct battery_usage *usage, int total_size)
+static void heart_battery_save_usage(char *key, struct battery_usage *usage, int total_size)
{
int i, len, num;
char buf[BATTERY_DATA_MAX] = {0, };
- if (!key || !usage)
- return RESOURCED_ERROR_FAIL;
+ assert(key);
+ assert(usage);
+
len = 0;
num = total_size/sizeof(struct battery_usage);
for (i = 0; i < num; i++) {
usage[i].cap_counter[CHARGING]);
}
logging_leveldb_put(key, strlen(key), buf, len);
- return RESOURCED_ERROR_NONE;
};
-static int heart_battery_save_prediction(char *key, struct battery_prediction *prediction)
+static void heart_battery_save_prediction(char *key, struct battery_prediction *prediction)
{
int i, len;
char buf[BATTERY_DATA_MAX] = {0, };
- if (!key || !prediction)
- return RESOURCED_ERROR_FAIL;
+ assert(key);
+ assert(prediction);
+
len = 0;
for (i = 0; i < MAX_STRATEGY; i++) {
len += snprintf(buf + len, BATTERY_DATA_MAX - len, "%ld %ld %ld %ld %ld %ld ",
prediction[CHARGING].time_pred_min[i]);
}
logging_leveldb_put(key, strlen(key), buf, len);
- return RESOURCED_ERROR_NONE;
};
/* ======================== Serialization/Deserialization ==================== */
-static int heart_battery_status_save_to_db(void)
+static void heart_battery_status_save_to_db(void)
{
heart_battery_save_used_time(BATTERY_USED_TIME, &batt_used);
heart_battery_save_status(BATTERY_STATUS, &batt_stat);
heart_battery_save_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage));
heart_battery_save_prediction(BATTERY_PREDICTION, batt_stat.prediction);
- return RESOURCED_ERROR_NONE;
}
static int heart_battery_status_read_from_db(void)
{
- heart_battery_load_used_time(BATTERY_USED_TIME, &batt_used);
- heart_battery_load_status(BATTERY_STATUS, &batt_stat);
+ bool ok = true;
- heart_battery_load_usage(BATTERY_RESET_USAGE, batt_stat.batt_reset_usage, sizeof(batt_stat.batt_reset_usage));
- heart_battery_load_usage(BATTERY_WEEK_DAY_USAGE, batt_stat.week_day_usage, sizeof(batt_stat.week_day_usage));
- heart_battery_load_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage));
+ ok &= (RESOURCED_ERROR_NONE == heart_battery_load_used_time(BATTERY_USED_TIME, &batt_used));
+ ok &= (RESOURCED_ERROR_NONE == heart_battery_load_status(BATTERY_STATUS, &batt_stat));
- heart_battery_load_prediction(BATTERY_PREDICTION, batt_stat.prediction);
- return RESOURCED_ERROR_NONE;
+ ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_RESET_USAGE, batt_stat.batt_reset_usage, sizeof(batt_stat.batt_reset_usage)));
+ ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_WEEK_DAY_USAGE, batt_stat.week_day_usage, sizeof(batt_stat.week_day_usage)));
+ ok &= (RESOURCED_ERROR_NONE == heart_battery_load_usage(BATTERY_LEVEL_USAGE, batt_stat.batt_lvl_usage, sizeof(batt_stat.batt_lvl_usage)));
+
+ ok &= (RESOURCED_ERROR_NONE == heart_battery_load_prediction(BATTERY_PREDICTION, batt_stat.prediction));
+
+ return ok ? RESOURCED_ERROR_NONE : RESOURCED_ERROR_FAIL;
}
static int heart_battery_capacity_save_to_file(char *filename)
heart_battery_get_file_commit_timestamp() + HEART_BATTERY_SAVE_INTERVAL >= now)
return;
- ret = heart_battery_status_save_to_db();
- if (ret)
- _E("failed to save status db");
+ heart_battery_status_save_to_db();
ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
if (ret)
static void dbus_battery_save_to_file(GDBusMethodInvocation *invocation, GVariant *params)
{
- int ret;
+ heart_battery_status_save_to_db();
- ret = heart_battery_status_save_to_db();
- if (ret) {
- _E("save to db failed");
- D_BUS_REPLY_NULL(invocation)
- return;
- }
- ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
+ int ret = heart_battery_capacity_save_to_file(HEART_BATTERY_CAPACITY_DATA_FILE);
if (ret) {
_E("save to file failed");
D_BUS_REPLY_NULL(invocation)
ci->state);
}
}
- len += snprintf(buf + len, CPU_DATA_MAX - len, "\n");
+ snprintf(buf + len, CPU_DATA_MAX - len, "\n");
fputs(buf, fp);
}
ret = pthread_mutex_unlock(&heart_cpu_mutex);
ci->utime = utime;
ci->stime = stime;
ci->state = state;
- table->last_pid_info = NULL;
- table->last_pid_info = g_slist_prepend(table->last_pid_info, ci);
+ table->last_pid_info = g_slist_prepend(NULL, ci);
table->last_pid = pid;
g_hash_table_insert(cpu_usage_list, (gpointer)table->appid, (gpointer)table);
}
info = (char*)data;
- sscanf(info, "%d "STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_APPID_LENGTH_M1),
- &pid, old_appid, new_appid);
+ if (sscanf(info, "%d "STR_FS(MAX_APPID_LENGTH_M1)" "STR_FS(MAX_APPID_LENGTH_M1),
+ &pid, old_appid, new_appid) < 0) {
+ _E("sscanf failed, %m");
+ return RESOURCED_ERROR_FAIL;
+ }
return logging_modify_appid(CPU_NAME, old_appid, new_appid, pid);
}
#include <sqlite3.h>
#include <time.h>
-#define MEM_NAME "memory"
-#define MEM_DATA_MAX 1024
-#define MEM_ARRAY_MAX 24
-#define MEM_FILE_SEPERATOR '@'
-
-#define HEART_MEMORY_SAVE_INTERVAL 3600 /* 1 hour */
-#define HEART_MEMORY_FILE HEART_FILE_PATH"/.memory.dat"
-
struct heart_memory_info {
unsigned int max_rss;
unsigned int avg_rss;
}
}
- len += snprintf(buf + len, MEM_DATA_MAX - len, "%c\n", MEM_FILE_SEPERATOR);
+ snprintf(buf + len, MEM_DATA_MAX - len, "%c\n", MEM_FILE_SEPERATOR);
fputs(buf, fp);
}
#define HEART_USER_FILE_PATH "%s/data/heart"
#define HEART_CONF_SECTION "HEART"
+#define MEM_NAME "memory"
+#define MEM_DATA_MAX 1024
+#define MEM_ARRAY_MAX 24
+#define MEM_FILE_SEPERATOR '@'
+
+#define HEART_MEMORY_SAVE_INTERVAL 3600 /* 1 hour */
+#define HEART_MEMORY_FILE HEART_FILE_PATH"/.memory.dat"
+
struct heart_module_ops {
char *name;
int (*init) (void *data);
char buf[LOGGING_BUF_MAX];
char key[20];
FILE *fp = NULL;
- int uid = -1;
+ int ret = -1;
if (pid == PID_FOR_ROOT)
return UID_FOR_ROOT;
}
while (fgets(buf, LOGGING_BUF_MAX, fp) != NULL) {
- sscanf(buf, "%19s %d", key, &uid);
- if (!strncmp(key, "Uid:", sizeof("Uid:") + 1)) {
- fclose(fp);
- return uid;
+ int uid;
+ if (sscanf(buf, "%19s %d", key, &uid) < 0) {
+ _E("sscanf failed: %m");
+ break;
+ }
+ if (!strncmp(key, "Uid:", sizeof("Uid:"))) {
+ ret = uid;
+ break;
}
}
fclose(fp);
- return -1;
+ return ret;
}
static struct logging_module *logging_find_module(char *name)
return RESOURCED_ERROR_DB_FAILED;
}
+ db_elem = NULL;
uid = malloc(sizeof(uid_t));
- assert(uid);
+ if (!uid)
+ goto oom_failure;
*uid = elem->uid;
db_elem = (struct logging_db*)malloc(sizeof(struct logging_db));
- assert(db_elem);
+ if (!db_elem)
+ goto oom_failure;
db_elem->path = strndup(path, strlen(path));
- assert(db_elem->path);
+ if (!db_elem->path)
+ goto oom_failure;
db_elem->file = file;
db_elem->insert_stmt = NULL;
}
return RESOURCED_ERROR_NONE;
+
+oom_failure:
+ free(uid);
+ if (db_elem)
+ free(db_elem->path);
+ free(db_elem);
+
+ _E("out of memory!");
+ return RESOURCED_ERROR_OUT_OF_MEMORY;
}
int logging_module_init(char *name, enum logging_period max_period,
if (!logging_instance) {
logging_instance = (struct logging_object *)malloc(sizeof(struct logging_object));
- assert(logging_instance);
+ if (!logging_instance) {
+ _E("out of memory");
+ return RESOURCED_ERROR_OUT_OF_MEMORY;
+ }
logging_instance->ref = 0;
ret = logging_init(NULL);
}
module = calloc(1, sizeof(struct logging_module));
- assert(module);
+ if (!module) {
+ _E("out of memory");
+ return RESOURCED_ERROR_OUT_OF_MEMORY;
+ }
/* DB create */
switch (db_type) {
snprintf(buf, PATH_MAX, "%s/%s", memcg, MEMCG_EVENTFD_CONTROL);
cgfd = open(buf, O_WRONLY);
if (cgfd < 0) {
+ const int saved_errno = errno;
_E("open event_control failed");
+ errno = saved_errno;
return RESOURCED_ERROR_FAIL;
}
snprintf(buf, PATH_MAX, "%s/%s", memcg, event);
mcgfd = open(buf, O_RDONLY);
if (mcgfd < 0) {
+ const int saved_errno = errno;
_E("open memory control failed");
+ errno = saved_errno;
return RESOURCED_ERROR_FAIL;
}
sz += 1;
res = write(cgfd, buf, sz);
if (res != sz) {
+ int saved_errno = errno;
_E("write cgfd failed : %d", res);
+ errno = saved_errno;
return RESOURCED_ERROR_FAIL;
}
return evfd;
}
len = strlen(dir);
- if (len <= 0 || len >= BUF_MAX -1) {
+ if (len <= 0 || len >= sizeof fpath - 1) {
_E("Invalid parameter - Directory path is too short or too long");
return RESOURCED_ERROR_INVALID_PARAMETER;
}
return RESOURCED_ERROR_NONE;
}
- strncpy(fpath, dir, len);
+ strncpy(fpath, dir, sizeof fpath);
+ fpath[sizeof fpath - 1] = '\0';
fname = fpath + len;
*fname++ = '/';
- len = BUF_MAX - len - 1;
+ len = sizeof fpath - len - 1;
for (i = 0; i < n; i++) {
if (i < NUM_RM_LOGS) {
if (strlen(namelist[i]->d_name) > len - 1)
continue;
strncpy(fname, namelist[i]->d_name, len - 1);
- fpath[BUF_MAX - 1] = '\0';
+ fpath[sizeof fpath - 1] = '\0';
_D("remove log file %s", fpath);
ret = remove(fpath);
if (ret < 0)
struct memcg_info *mi;
int ret, memcg_idx, should_swap = 0;
- if (!pai) {
+ if (!pai)
return;
- } else if (oom_score_adj >= OOMADJ_BACKGRD_PERCEPTIBLE &&
+
+ if (oom_score_adj >= OOMADJ_BACKGRD_PERCEPTIBLE &&
oom_score_adj < OOMADJ_BACKGRD_UNLOCKED) {
/* We'd like lowmem a chance to do a bit more with some
* long-lived processes such as background-locked or
memcg_idx = MEMCG_BGLOCKED;
mi = memcg_tree[memcg_idx]->info;
} else if (oom_score_adj > OOMADJ_BACKGRD_UNLOCKED + OOMADJ_APP_INCREASE) {
- if (pai && (oom_score_adj != pai->memory.oom_score_adj))
+ if (oom_score_adj != pai->memory.oom_score_adj)
proc_set_process_memory_state(pai, pai->memory.memcg_idx,
- pai->memory.memcg_info, oom_score_adj);
+ pai->memory.memcg_info, oom_score_adj);
return;
} else if (oom_score_adj >= OOMADJ_INIT) {
memcg_idx = MEMCG_APPS;
GSList *iter = NULL;
enum lmk_type lmk_type = LMK_MEMORY;
+ // FIXME: probably shouldn't get ignored
(void)lowmem_press_eventfd_read(fd);
for (i = 0; i < MEMCG_MAX; i++) {
return true;
}
-static void lowmem_press_register_eventfd(struct memcg_info *mi)
+static int lowmem_press_register_eventfd(struct memcg_info *mi)
{
int evfd;
const char *name = mi->name;
static fd_handler_h handler;
if (mi->threshold[LOWMEM_MEDIUM] == LOWMEM_THRES_INIT)
- return;
+ return 0;
evfd = memcg_set_eventfd(name, MEMCG_EVENTFD_MEMORY_PRESSURE,
event_level);
- if (evfd < 0) {
+ if (evfd == RESOURCED_ERROR_FAIL) {
+ int saved_errno = errno;
_I("fail to register event press fd %s cgroup", name);
- return;
+ return -saved_errno;
}
mi->evfd = evfd;
_I("register event fd success for %s cgroup", name);
add_fd_read_handler(evfd, lowmem_press_eventfd_handler, NULL, NULL, &handler);
- return;
+ return 0;
}
static int lowmem_press_setup_eventfd(void)
if (!memcg_tree[i]->use_hierarchy)
continue;
- lowmem_press_register_eventfd(memcg_tree[i]->info);
+ const int r = lowmem_press_register_eventfd(memcg_tree[i]->info);
+ if (r < 0)
+ return RESOURCED_ERROR_FAIL;
}
return RESOURCED_ERROR_NONE;
}
static void dbus_reclaim_memory(GDBusMethodInvocation *invocation, GVariant *params)
{
- int ret = -1;
-
_D("reclaiming memory!");
- ret = proc_sys_node_trigger(SYS_VM_SHRINK_MEMORY);
- ret = proc_sys_node_trigger(SYS_VM_COMPACT_MEMORY);
+ bool ok = true;
+ ok &= (RESOURCED_ERROR_NONE == proc_sys_node_trigger(SYS_VM_SHRINK_MEMORY));
+ ok &= (RESOURCED_ERROR_NONE == proc_sys_node_trigger(SYS_VM_COMPACT_MEMORY));
- g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ret));
+ g_dbus_method_invocation_return_value(invocation, g_variant_new("(i)", ok ? RESOURCED_ERROR_NONE : RESOURCED_ERROR_FAIL));
}
static void turn_off_vip_handler()
msg->type = MEMCG_SWAP;
ret = swap_move_to_cgroup(msg->info, candidates);
out:
- if (candidates)
- g_array_free(candidates, TRUE);
+ g_array_free(candidates, TRUE);
return ret;
}
r = cgroup_read_node_int32(LOWMEM_ROOT_CGROUP,
MEMCG_SWAPNESS_PATH, ¤t_swappiness);
+ if (r)
+ return;
if (swap_get_state() == SWAP_ON)
return;
swap_total = proc_get_swap_total();
r = memcg_get_swap_usage(LOWMEM_SWAP_CGROUP, &swap_usage);
+ if (r)
+ return r;
swapcg_usage_ratio = (float)(swap_usage / (swap_total - swap_available) *100);
if (swapcg_usage_ratio > SWAPCG_CHECK_RATIO)
type = LMK_OLDEST;
static int resourced_vip_process_finalize(void *data)
{
- strv_free_full(arg_vip_proc_names);
- strv_free_full(arg_vip_systemd_services);
+ strv_free_full(&arg_vip_proc_names);
+ strv_free_full(&arg_vip_systemd_services);
vip_process_disable(NULL);
unregister_notifier(RESOURCED_NOTIFIER_BOOTING_DONE, vip_booting_done);