From be74f3995c12b204e769dd844dae66edebc9bbcc Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Wed, 28 Nov 2018 00:21:36 +0000 Subject: Fix memory leaks and add 'kill' verb Signed-off-by: Vitaly Wool Change-Id: Idf75bb1ce703300f9b918969289aba7df9b2a182 --- binding/task-manager-binding.c | 167 ++++++++++++++++++++++++----------------- 1 file changed, 98 insertions(+), 69 deletions(-) (limited to 'binding') diff --git a/binding/task-manager-binding.c b/binding/task-manager-binding.c index 43c9ee3..932a707 100644 --- a/binding/task-manager-binding.c +++ b/binding/task-manager-binding.c @@ -6,17 +6,13 @@ #include #include #include +#include +#include +#include #define AFB_BINDING_VERSION 2 #include -void get_process_list(struct afb_req request); -struct pstat* fill_pstat(proc_t *proc_info); -struct cpu_percentage* cpu_calculate(struct pstat*, struct pstat*); -struct process_container* process_container_constr(char* process_name, int euid, struct pstat *pstat_values); -static const struct afb_binding_interface *interface; -static struct afb_event event; - struct pstat { long long unsigned int utime_ticks; long long unsigned int cutime_ticks; @@ -32,77 +28,110 @@ struct cpu_percentage { struct process_container { char *process_name; - // int tid; int euid; - struct pstat *pstat_values; + struct pstat pstat_values; }; +void get_process_list(struct afb_req request); +int fill_pstat(proc_t *proc_info, struct pstat *pstat); +void cpu_calculate(struct pstat*, struct pstat*, struct cpu_percentage *perc); +void fill_process_container(char* process_name, int euid, struct pstat *pstat_values, struct process_container *pc); + void get_process_list(struct afb_req request){ - int seconds = 1, page_size; - page_size = getpagesize(); - struct pstat *last_pstat_values, *now_pstat_values; - struct cpu_percentage *cpu_usage; + struct pstat last_pstat_values, cur_pstat_values; + struct cpu_percentage cpu_usage; struct process_container *process_obj, *elem = NULL; - struct process_container* object_container[65535]; // array holding process objects + struct process_container *object_container[65535]; // array holding process objects struct json_object *ret_json, *json_array, *json_obj; ret_json = json_object_new_object(); json_array = json_object_new_array(); char state_str[2] = "\0"; + int i, ret; PROCTAB* proc = openproc(PROC_FILLMEM | PROC_FILLSTAT); if (!proc){ AFB_REQ_ERROR(request, "Unable to open /proc!"); - afb_req_fail_f(request, "Failed", "Error processing arguments."); + afb_req_fail(request, "Failed", "Error processing arguments."); + return; } + memset(object_container, 0, sizeof(*object_container)); proc_t* proc_info; while ((proc_info = readproc(proc, NULL)) != NULL) { - last_pstat_values = fill_pstat(proc_info); - process_obj = process_container_constr(proc_info->cmd, proc_info->euid, last_pstat_values); + ret = fill_pstat(proc_info, &last_pstat_values); + if (ret < 0) { + AFB_REQ_ERROR(request, "fill_pstat failed"); + continue; + } + process_obj = malloc(sizeof(*process_obj)); + if (process_obj == NULL) { + AFB_REQ_ERROR(request, "allocation of process_obj failed"); + continue; + } + fill_process_container(proc_info->cmd, proc_info->euid, &last_pstat_values, process_obj); object_container[proc_info->tid] = process_obj; freeproc(proc_info); } - sleep(seconds); + sleep(1); + closeproc(proc); proc = openproc(PROC_FILLMEM | PROC_FILLSTAT); if (!proc){ AFB_REQ_ERROR(request, "Unable to open /proc!"); - afb_req_fail_f(request, "Failed", "Error processing arguments."); + afb_req_fail(request, "Failed", "Error processing arguments."); + return; } - proc_t* proc_info2; - while ((proc_info2 = readproc(proc, NULL)) != NULL) { - now_pstat_values = fill_pstat(proc_info2); - elem = object_container[proc_info2->tid]; - if(elem){ - cpu_usage = cpu_calculate(elem->pstat_values, now_pstat_values); + while ((proc_info = readproc(proc, NULL)) != NULL) { + ret = fill_pstat(proc_info, &cur_pstat_values); + if (ret < 0) { + AFB_REQ_ERROR(request, "fill_pstat failed"); + continue; + } + elem = object_container[proc_info->tid]; + if (elem) { + cpu_calculate(&elem->pstat_values, &cur_pstat_values, &cpu_usage); json_obj = json_object_new_object(); - json_object_object_add(json_obj, "cmd", json_object_new_string(proc_info2->cmd)); - json_object_object_add(json_obj, "tid", json_object_new_int(proc_info2->tid)); - json_object_object_add(json_obj, "euid", json_object_new_int(proc_info2->euid)); - json_object_object_add(json_obj, "scpu", json_object_new_double(cpu_usage->scpu_usage)); - json_object_object_add(json_obj, "ucpu", json_object_new_double(cpu_usage->ucpu_usage)); - json_object_object_add(json_obj, "resident_mem", json_object_new_double((proc_info2->resident * page_size)/ pow(1024, 2))); - state_str[0] = proc_info2->state; + json_object_object_add(json_obj, "cmd", json_object_new_string(proc_info->cmd)); + json_object_object_add(json_obj, "tid", json_object_new_int(proc_info->tid)); + json_object_object_add(json_obj, "euid", json_object_new_int(proc_info->euid)); + json_object_object_add(json_obj, "scpu", json_object_new_double(cpu_usage.scpu_usage)); + json_object_object_add(json_obj, "ucpu", json_object_new_double(cpu_usage.ucpu_usage)); + json_object_object_add(json_obj, "resident_mem", json_object_new_double((proc_info->resident * getpagesize())/ pow(1024, 2))); + state_str[0] = proc_info->state; json_object_object_add(json_obj, "state", json_object_new_string(state_str)); json_object_array_add(json_array, json_obj); } - freeproc(proc_info2); + freeproc(proc_info); } json_object_object_add(ret_json, "processes", json_array); afb_req_success(request, ret_json, NULL); closeproc(proc); - // printf ("The json object created: %s\n", json_object_to_json_string(ret_json)); } -struct pstat* fill_pstat(proc_t *proc_info){ +void kill_process(struct afb_req request) +{ + struct json_object *ret_json; + ret_json = json_object_new_object(); + json_object *queryJ = afb_req_json(request); + int tid = json_object_get_int(queryJ); + int ret; + + AFB_REQ_INFO(request, "killing %d\n", tid); + /* XXX: add checks */ + ret = kill(tid, SIGTERM); + if (ret < 0) + afb_req_fail_f(request, "Failed", "Error %d", errno); + /* we don't signal success, there's no use for it */ +} + - long unsigned int cpu_total_time; - long unsigned int cpu_time[10]; - struct pstat *pstat_values = malloc(sizeof(struct pstat)); +int fill_pstat(proc_t *proc_info, struct pstat *pstat_values) +{ + long unsigned int cpu_time[9]; pstat_values->utime_ticks = proc_info->utime; pstat_values->cutime_ticks = proc_info->cutime; @@ -110,53 +139,46 @@ struct pstat* fill_pstat(proc_t *proc_info){ pstat_values->cstime_ticks = proc_info->cstime; FILE *fstat = fopen("/proc/stat", "r"); - if (fstat == NULL) { - perror("FOPEN ERROR "); - fclose(fstat); - } + if (fstat == NULL) + return -1; memset(cpu_time, 0, sizeof(cpu_time)); - if (fscanf(fstat, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", - &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3], - &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7], - &cpu_time[8], &cpu_time[9]) == EOF) { - fclose(fstat); - } + fscanf(fstat, "%*s %lu %lu %lu %lu %*lu %lu %lu %lu %lu %lu", + &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3], + &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7], + &cpu_time[8]); fclose(fstat); /* * Returns total CPU time. It is a sum of user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice + * + * */ - for(int i = 0; i < 10; i++) + pstat_values->cpu_total_time = 0; + for(int i = 0; i < 9; i++) pstat_values->cpu_total_time += cpu_time[i]; - return pstat_values; + return 0; } -struct cpu_percentage* cpu_calculate(struct pstat *last_pstat_values, struct pstat *now_pstat_values){ - - long unsigned int total_time_diff = now_pstat_values->cpu_total_time - last_pstat_values->cpu_total_time; - - struct cpu_percentage *cpu_values = malloc(sizeof(struct cpu_percentage)); +void cpu_calculate(struct pstat *last_pstat_values, struct pstat *cur_pstat_values, struct cpu_percentage *cpu_values) +{ - cpu_values->ucpu_usage = 100 * (((now_pstat_values->utime_ticks + now_pstat_values->cutime_ticks) - - (last_pstat_values->utime_ticks + last_pstat_values->cutime_ticks)) / (double) total_time_diff); + long unsigned int total_time_diff = cur_pstat_values->cpu_total_time - last_pstat_values->cpu_total_time; - cpu_values->scpu_usage = 100 * (((now_pstat_values->stime_ticks + now_pstat_values->cstime_ticks) - - (last_pstat_values->stime_ticks + last_pstat_values->cstime_ticks)) / (double) total_time_diff); + cpu_values->ucpu_usage = 100.0 * (((cur_pstat_values->utime_ticks + cur_pstat_values->cutime_ticks) + - (last_pstat_values->utime_ticks + last_pstat_values->cutime_ticks)) / (double) total_time_diff); - return cpu_values; + cpu_values->scpu_usage = 100.0 * (((cur_pstat_values->stime_ticks + cur_pstat_values->cstime_ticks) + - (last_pstat_values->stime_ticks + last_pstat_values->cstime_ticks)) / (double) total_time_diff); } -struct process_container* process_container_constr(char* process_name, int euid, struct pstat *pstat_values) { - - struct process_container *r = malloc(sizeof(struct process_container)); - r->process_name = process_name; - r->euid = euid; - r->pstat_values = pstat_values; - - return r; +void fill_process_container(char *process_name, int euid, struct pstat *pstat_values, struct process_container *pc) +{ + pc->process_name = process_name; + pc->euid = euid; + pc->pstat_values = *pstat_values; } static const struct afb_verb_v2 _afb_verbs_v2_taskmanager[] = { @@ -166,6 +188,13 @@ static const struct afb_verb_v2 _afb_verbs_v2_taskmanager[] = { .auth = NULL, .info = "Get an array of all processes currently running on the system", .session = AFB_SESSION_NONE_V2 + }, + { + .verb = "kill_process", + .callback = kill_process, + .auth = NULL, + .info = "Kill the process specified by tid", + .session = AFB_SESSION_NONE_V2 } }; @@ -176,4 +205,4 @@ const struct afb_binding_v2 afbBindingV2 = { .info = "Task Manager service", .verbs = _afb_verbs_v2_taskmanager, .noconcurrency = 0 -}; \ No newline at end of file +}; -- cgit 1.2.3-korg