#define MEMLIMIT_CONFIG_BGAPP MEMLIMIT_CONFIG_LIM_PFX "BgApp"
#define MIN_LIMIT_VALUE MBYTE_TO_BYTE(1) /* Byte */
-enum mem_limit_type {
- /* check only swap usage also */
+/*enum mem_limit_type {
MEM_LIMIT_NONE,
- /* register OOM event and control application in kernel side */
MEM_LIMIT_OOM,
- /* register threshold event and control application in resourced*/
MEM_LIMIT_TRHESHOLD,
};
-static enum mem_limit_type mem_limit;
+static enum mem_limit_type mem_limit;*/
static GHashTable *memory_limit_hash;
static unsigned int mem_guiapp_limit;
static unsigned int mem_bgapp_limit;
-static int mem_service_action = PROC_ACTION_KILL;
-static int mem_widget_action = PROC_ACTION_KILL;
-static int mem_guiapp_action = PROC_ACTION_KILL;
-static int mem_bgapp_action = PROC_ACTION_KILL;
-
-struct memory_info {
- pid_t pid;
- unsigned int size;
-};
-
-struct memory_limit_log {
- pid_t pid;
- char *appname;
- char *cgdir;
-};
-
-static int get_pid_use_max_memory(GArray *pids_array, unsigned int *max_mem)
-{
- int i, ret;
- struct memory_info mi = {0, 0};
-
- if (!pids_array->len)
- return RESOURCED_ERROR_NO_DATA;
-
- for (i = 0; i < pids_array->len; i++) {
- pid_t mpid = 0;
- unsigned int size;
-
- mpid = g_array_index(pids_array, pid_t, i);
- if (!mpid)
- continue;
-
- ret = proc_get_mem_usage(mpid, &size);
- if (ret != RESOURCED_ERROR_NONE)
- continue;
-
- _D("%d used %d memory", mpid, size);
-
- if (size > mi.size) {
- mi.pid = mpid;
- mi.size = size;
- }
- }
- *max_mem = mi.size;
- _D("%d used max %d memory", mi.pid, mi.size);
- return mi.pid;
-}
-
-static pid_t get_main_pid(const char *dir, unsigned int *max_mem)
-{
- GArray *pids_array = NULL;
- _cleanup_free_ char *path = NULL;
- int ret;
- pid_t main_pid;
-
- ret = asprintf(&path, "%s/", dir);
- if (ret < 0)
- return -ENOMEM;
-
- ret = cgroup_get_pids(path, &pids_array);
- if (ret < 0 || !pids_array->len) {
- g_array_free(pids_array, true);
- return RESOURCED_ERROR_NO_DATA;
- }
-
- main_pid = get_pid_use_max_memory(pids_array, max_mem);
- g_array_free(pids_array, true);
- return main_pid;
-}
+static int mem_service_action = PROC_ACTION_IGNORE;
+static int mem_widget_action = PROC_ACTION_IGNORE;
+static int mem_guiapp_action = PROC_ACTION_IGNORE;
+static int mem_bgapp_action = PROC_ACTION_IGNORE;
static void memory_limit_hash_destroy(gpointer data)
{
goto timer_out;
}
- if (mle->pid <= 0) {
- _E("[DEBUG] pid should be larger than 0");
+ if (mle->pids_array == NULL) {
+ _E("[DEBUG] pids array should not be NULL");
goto mle_timer_init;
}
- if (kill(mle->pid, 0) == 0) {
- safe_kill(mle->pid, SIGKILL);
+ for (int i = 0; i < mle->pids_array->len; i++) {
+ pid_t pid = g_array_index(mle->pids_array, pid_t, i);
+ if (!pid)
+ continue;
+
+ if (kill(pid, 0) == 0) {
+ _I("[DEBUG] dir %s's pid (%d) is still avlie, so kill forcely", mle->path, pid);
+ safe_kill(pid, SIGKILL);
+ }
}
+ g_array_free(mle->pids_array, true);
+
mle_timer_init:
- mle->pid = -1;
+ mle->pids_array = NULL;
timer_out:
return G_SOURCE_REMOVE;
}
static bool memory_action_cb(int fd, void *data)
{
int result;
- pid_t main_pid;
- uint32_t usage, max_mem;
+ pid_t pid;
+ GArray *pids_array = NULL;
+ uint32_t usage;
uint64_t dummy_efd;
char *cg_dir = (char *)data;
struct memory_limit_event *mle;
- _cleanup_free_ struct cgroup_memory_stat *mem_stat = NULL;
mle = g_hash_table_lookup(memory_limit_hash, cg_dir);
if (!mle) {
return true;
}
- result = memcg_get_memory_stat(cg_dir, &mem_stat);
- if (result < 0) {
- _E("[DEBUG] Failed to get memory status : %s", cg_dir);
- goto remove_mle;
- }
-
switch (mle->action) {
case PROC_ACTION_BROADCAST:
- main_pid = get_main_pid(cg_dir, &max_mem);
- if (main_pid <= 0) {
- _D("[DEBUG] there is no victim, removed cgroup : %s", cg_dir);
+ result = cgroup_get_pids(cg_dir, &pids_array);
+ if (result < 0 || !pids_array->len) {
+ g_array_free(pids_array, true);
goto remove_mle;
}
- if (lowmem_limit_broadcast(main_pid)) {
- _E("[DEBUG] Failed to broadcast of process (%s)", cg_dir);
- return false;
+ for (int i = 0; i < pids_array->len; i++) {
+ pid = g_array_index(pids_array, pid_t, i);
+ if (!pid)
+ continue;
+
+ if (lowmem_limit_broadcast(pid)) {
+ _E("[DEBUG] Failed to broadcast of process (%s)", cg_dir);
+ safe_kill(pid, SIGTERM);
+ }
}
+
+ g_array_free(pids_array, true);
break;
case PROC_ACTION_RECLAIM:
lowmem_trigger_swap(0, cg_dir, false);
break;
case PROC_ACTION_KILL:
- main_pid = get_main_pid(cg_dir, &max_mem);
- if (main_pid <= 0) {
- _D("[DEBUG] there is no victim, removed cgroup : %s", cg_dir);
+ result = cgroup_get_pids(cg_dir, &pids_array);
+ if (result < 0 || !pids_array->len) {
+ g_array_free(pids_array, true);
goto remove_mle;
}
- safe_kill(main_pid, SIGTERM);
- if (mle->pid == -1) {
- mle->pid = main_pid;
+ for (int i = 0; i < pids_array->len; i++) {
+ pid = g_array_index(pids_array, pid_t, i);
+ if (!pid)
+ continue;
+
+ safe_kill(pid, SIGTERM);
+ }
+
+ if (mle->pids_array == NULL) {
+ mle->pids_array = pids_array;
g_timeout_add_seconds(2, liveness_check_cb, mle);
}
+ else
+ g_array_free(pids_array, true);
break;
default:
}
mle->action = action;
mle->threshold = limit;
- mle->pid = -1;
+ mle->pids_array = NULL;
add_fd_read_handler(fd, memory_action_cb, mle->path, NULL, &fdh);
mle->fdh = fdh;
g_hash_table_insert(memory_limit_hash, (gpointer)mle->path,
return;
}
+ if (action == PROC_ACTION_IGNORE)
+ return;
+
if (!name) {
_E("[DEBUG] service name is NULL");
return;
if (ps->pai && ps->pai->memory.memlimit_update_exclude)
return RESOURCED_ERROR_NONE;
- if (mem_service_limit) {
+ if (mem_service_limit && mem_service_action != PROC_ACTION_IGNORE) {
lowmem_limit_set_app(mem_service_limit, ps->pai, mem_service_action);
}
return RESOURCED_ERROR_NONE;
if (ps->pai && ps->pai->memory.memlimit_update_exclude)
return RESOURCED_ERROR_NONE;
- if (mem_guiapp_limit && ps->pai->type == PROC_TYPE_GUI) {
+ if (mem_guiapp_limit && mem_guiapp_action != PROC_ACTION_IGNORE &&
+ ps->pai->type == PROC_TYPE_GUI) {
lowmem_limit_set_app(mem_guiapp_limit, ps->pai, mem_guiapp_action);
}
- if (mem_widget_limit && ps->pai->type == PROC_TYPE_WIDGET) {
+
+ if (mem_widget_limit && mem_widget_action != PROC_ACTION_IGNORE &&
+ ps->pai->type == PROC_TYPE_WIDGET) {
lowmem_limit_set_app(mem_widget_limit, ps->pai, mem_widget_action);
}
int result;
unsigned int usage;
- mem_limit = MEM_LIMIT_TRHESHOLD;
result = cgroup_read_node_uint32(MEMCG_PATH, MEMCG_SWAP_USAGE, &usage);
if (result == RESOURCED_ERROR_NONE)
registerpath = MEMCG_SWAP_USAGE;
register_notifier(RESOURCED_NOTIFIER_LIMIT_SYSTEM_SERVICE, lowmem_limit_system_service);
register_notifier(RESOURCED_NOTIFIER_LIMIT_APP, lowmem_limit_app);
- if (mem_limit == MEM_LIMIT_NONE)
- return;
- if (mem_service_limit)
+ if (mem_service_limit && mem_service_action != PROC_ACTION_IGNORE)
register_notifier(RESOURCED_NOTIFIER_SERVICE_LAUNCH, lowmem_limit_service);
- if (mem_guiapp_limit || mem_widget_limit)
+ if ((mem_guiapp_limit && mem_guiapp_action != PROC_ACTION_IGNORE) ||
+ (mem_widget_limit && mem_widget_action != PROC_ACTION_IGNORE))
register_notifier(RESOURCED_NOTIFIER_APP_LAUNCH, lowmem_limit_appwidget);
- if (mem_bgapp_limit) {
- if (!mem_guiapp_limit || !mem_widget_limit) {
- _W("Background app limit requires that both GUIApp and Widget limits to be set to work properly. Ignoring.");
+ if (mem_bgapp_limit && mem_bgapp_action != PROC_ACTION_IGNORE) {
+ if (!(mem_guiapp_limit && mem_guiapp_action != PROC_ACTION_IGNORE) ||
+ !(mem_widget_limit && mem_widget_action != PROC_ACTION_IGNORE)) {
+ _W("[DEBUG] Background app limit requires that both GUIApp and Widget limits to be set to work properly. Ignoring.");
} else {
register_notifier(RESOURCED_NOTIFIER_APP_BACKGRD, lowmem_limit_bgapp);
register_notifier(RESOURCED_NOTIFIER_APP_FOREGRD, lowmem_limit_fgapp);