edi_process: Introduce new process API.
Introduced process querying API for all the platforms we currently support. With this we are able to get realiable data about system processes. We use this API to track running process instances launched from Edi. Also, this allows for a much cleaner implementation of the edi_debug code when tracking the debug process. Essentially using the new API to track both running instances and debugged instances. Moreover, simplifying this by using a timer in edi_main to keep track of these occurences. We can now reliably track use of the 'Run' command in the toolbar and menu. Adding a 'Terminate' to compliment. The UI now responds properly to running or non-running Edi launched process instances.
This commit is contained in:
parent
1ce49c9e8a
commit
06d866411d
|
@ -2,21 +2,19 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined (__APPLE__) || defined(__OpenBSD__)
|
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(__OpenBSD__)
|
|
||||||
#include <sys/proc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <Eo.h>
|
#include <Eo.h>
|
||||||
#include <Eina.h>
|
#include <Eina.h>
|
||||||
#include <Elementary.h>
|
#include <Elementary.h>
|
||||||
|
|
||||||
#include "edi_debug.h"
|
#include "edi_debug.h"
|
||||||
|
#include "edi_process.h"
|
||||||
#include "edi_config.h"
|
#include "edi_config.h"
|
||||||
#include "edi_private.h"
|
#include "edi_private.h"
|
||||||
|
|
||||||
|
@ -67,160 +65,77 @@ Edi_Debug_Tool *edi_debug_tool_get(const char *name)
|
||||||
return &_debugger_tools[0];
|
return &_debugger_tools[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
static int
|
||||||
static long int
|
_system_pid_max_get(void)
|
||||||
_sysctlfromname(const char *name, void *mib, int depth, size_t *len)
|
|
||||||
{
|
{
|
||||||
long int result;
|
static int pid_max = 0;
|
||||||
|
|
||||||
if (sysctlnametomib(name, mib, len) < 0) return -1;
|
if (pid_max > 0)
|
||||||
*len = sizeof(result);
|
return pid_max;
|
||||||
if (sysctl(mib, depth, &result, len, NULL, 0) < 0) return -1;
|
|
||||||
|
|
||||||
return result;
|
#if defined(__linux__)
|
||||||
}
|
FILE *f;
|
||||||
|
char buf[128];
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
f = fopen("/proc/sys/kernel/pid_max", "r");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
n = fread(buf, 1, sizeof(buf) - 1, f);
|
||||||
|
buf[n] = 0x00;
|
||||||
|
fclose(f);
|
||||||
|
pid_max = atoi(buf);
|
||||||
|
}
|
||||||
|
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||||
|
int mib[2] = { CTL_KERN, KERN_MAXPROC };
|
||||||
|
size_t len = sizeof(pid_max);
|
||||||
|
sysctl(mib, 2, &pid_max, &len, NULL, 0);
|
||||||
|
#elif defined(PID_MAX)
|
||||||
|
pid_max = PID_MAX;
|
||||||
#endif
|
#endif
|
||||||
|
if (pid_max <= 0)
|
||||||
|
pid_max = 99999;
|
||||||
|
|
||||||
|
return pid_max;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the process ID of the child process being debugged in *our* session */
|
/* Get the process ID of the child process being debugged in *our* session */
|
||||||
int edi_debug_process_id(Edi_Debug *debugger)
|
int edi_debug_process_id(Edi_Debug *debugger)
|
||||||
{
|
{
|
||||||
int my_pid, child_pid = -1;
|
Edi_Proc_Stats *p;
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined (__APPLE__) || defined(__OpenBSD__)
|
int pid_max, debugger_pid, child_pid = -1;
|
||||||
struct kinfo_proc kp;
|
|
||||||
int mib[6];
|
|
||||||
size_t len;
|
|
||||||
int max_pid, i;
|
|
||||||
|
|
||||||
|
if (!debugger) return -1;
|
||||||
if (!debugger->program_name) return -1;
|
if (!debugger->program_name) return -1;
|
||||||
if (!debugger->exe) return -1;
|
if (!debugger->exe) return -1;
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
debugger_pid = ecore_exe_pid_get(debugger->exe);
|
||||||
len = sizeof(max_pid);
|
|
||||||
max_pid = _sysctlfromname("kern.lastpid", mib, 2, &len);
|
|
||||||
#elif defined(PID_MAX)
|
|
||||||
max_pid = PID_MAX;
|
|
||||||
#else
|
|
||||||
max_pid = 99999;
|
|
||||||
#endif
|
|
||||||
my_pid = ecore_exe_pid_get(debugger->exe);
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
pid_max = _system_pid_max_get();
|
||||||
if (sysctlnametomib("kern.proc.pid", mib, &len) < 0) return -1;
|
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
mib[0] = CTL_KERN;
|
|
||||||
mib[1] = KERN_PROC;
|
|
||||||
mib[2] = KERN_PROC_PID;
|
|
||||||
mib[4] = sizeof(struct kinfo_proc);
|
|
||||||
mib[5] = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (i = my_pid; i <= max_pid; i++)
|
for (int i = 1; i <= pid_max; i++)
|
||||||
{
|
{
|
||||||
mib[3] = i;
|
p = edi_process_stats_by_pid(i);
|
||||||
len = sizeof(kp);
|
|
||||||
#if defined(__OpenBSD__)
|
|
||||||
if (sysctl(mib, 6, &kp, &len, NULL, 0) == -1) continue;
|
|
||||||
#else
|
|
||||||
if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1) continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
|
||||||
if (kp.ki_ppid != my_pid) continue;
|
|
||||||
if (strcmp(debugger->program_name, kp.ki_comm)) continue;
|
|
||||||
child_pid = kp.ki_pid;
|
|
||||||
if (kp.ki_stat == SRUN || kp.ki_stat == SSLEEP)
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
|
||||||
#elif defined(__OpenBSD__)
|
|
||||||
if (kp.p_ppid != my_pid) continue;
|
|
||||||
if (strcmp(debugger->program_name, kp.p_comm)) continue;
|
|
||||||
child_pid = kp.p_pid;
|
|
||||||
|
|
||||||
if (kp.p_stat == SRUN || kp.p_stat == SSLEEP)
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
|
||||||
#else /* APPLE */
|
|
||||||
if (kp.kp_proc.p_oppid != my_pid) continue;
|
|
||||||
if (strcmp(debugger->program_name, kp.kp_proc.p_comm)) continue;
|
|
||||||
child_pid = kp.kp_proc.p_pid;
|
|
||||||
if (kp.kp_proc.p_stat == SRUN || kp.kp_proc.p_stat == SSLEEP)
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
Eina_List *files, *l;
|
|
||||||
const char *temp_name;
|
|
||||||
char path[PATH_MAX];
|
|
||||||
char buf[4096];
|
|
||||||
char *p, *name, *end;
|
|
||||||
FILE *f;
|
|
||||||
int count, parent_pid, pid;
|
|
||||||
|
|
||||||
if (!debugger->program_name)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!debugger->exe) return -1;
|
|
||||||
|
|
||||||
my_pid = ecore_exe_pid_get(debugger->exe);
|
|
||||||
|
|
||||||
files = ecore_file_ls("/proc");
|
|
||||||
|
|
||||||
EINA_LIST_FOREACH(files, l, name)
|
|
||||||
{
|
|
||||||
pid = atoi(name);
|
|
||||||
if (!pid) continue;
|
|
||||||
snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
|
|
||||||
f = fopen(path, "r");
|
|
||||||
if (!f) continue;
|
|
||||||
p = fgets(buf, sizeof(buf), f);
|
|
||||||
fclose(f);
|
|
||||||
if (!p) continue;
|
if (!p) continue;
|
||||||
temp_name = ecore_file_file_get(buf);
|
|
||||||
if (!strcmp(temp_name, debugger->program_name))
|
if (p->ppid == debugger_pid)
|
||||||
{
|
{
|
||||||
parent_pid = 0;
|
if (!strcmp(debugger->program_name, p->command))
|
||||||
// Match success - program name with pid.
|
|
||||||
child_pid = pid;
|
|
||||||
snprintf(path, sizeof(path), "/proc/%d/stat", pid);
|
|
||||||
f = fopen(path, "r");
|
|
||||||
if (f)
|
|
||||||
{
|
{
|
||||||
count = 0;
|
child_pid = p->pid;
|
||||||
p = fgets(buf, sizeof(buf), f);
|
if (!strcmp(p->state, "RUN") ||!strcmp(p->state, "SLEEP"))
|
||||||
while (*p++ != '\0')
|
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
||||||
{
|
else
|
||||||
if (p[0] == ' ') { count++; p++; }
|
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
||||||
if (count == 2)
|
|
||||||
{
|
|
||||||
if (p[0] == 'S' || p[0] == 'R')
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_ACTIVE;
|
|
||||||
else
|
|
||||||
debugger->state = EDI_DEBUG_PROCESS_SLEEPING;
|
|
||||||
}
|
|
||||||
if (count == 3) break;
|
|
||||||
}
|
|
||||||
end = strchr(p, ' ');
|
|
||||||
if (end)
|
|
||||||
{
|
|
||||||
*end = '\0';
|
|
||||||
// parent pid matches - right process.
|
|
||||||
parent_pid = atoi(p);
|
|
||||||
}
|
|
||||||
fclose(f);
|
|
||||||
}
|
}
|
||||||
if (parent_pid == my_pid)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
if (child_pid != -1)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files)
|
|
||||||
eina_list_free(files);
|
|
||||||
#endif
|
|
||||||
return child_pid;
|
return child_pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -197,11 +197,14 @@ _edi_debugpanel_button_start_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UN
|
||||||
edi_debugpanel_start(_edi_project_config_debug_command_get());
|
edi_debugpanel_start(_edi_project_config_debug_command_get());
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
void
|
||||||
_edi_debug_active_check_cb(void *data EINA_UNUSED)
|
edi_debugpanel_active_check(void)
|
||||||
{
|
{
|
||||||
|
Edi_Debug *debug;
|
||||||
int pid;
|
int pid;
|
||||||
Edi_Debug *debug = edi_debug_get();
|
|
||||||
|
debug = edi_debug_get();
|
||||||
|
if (!debug) return;
|
||||||
|
|
||||||
pid = ecore_exe_pid_get(debug->exe);
|
pid = ecore_exe_pid_get(debug->exe);
|
||||||
if (pid == -1)
|
if (pid == -1)
|
||||||
|
@ -212,16 +215,11 @@ _edi_debug_active_check_cb(void *data EINA_UNUSED)
|
||||||
elm_object_disabled_set(_button_start, EINA_FALSE);
|
elm_object_disabled_set(_button_start, EINA_FALSE);
|
||||||
elm_object_disabled_set(_button_int, EINA_TRUE);
|
elm_object_disabled_set(_button_int, EINA_TRUE);
|
||||||
elm_object_disabled_set(_button_term, EINA_TRUE);
|
elm_object_disabled_set(_button_term, EINA_TRUE);
|
||||||
return ECORE_CALLBACK_RENEW;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!debug)
|
|
||||||
return ECORE_CALLBACK_RENEW;
|
|
||||||
|
|
||||||
pid = edi_debug_process_id(debug);
|
pid = edi_debug_process_id(debug);
|
||||||
_edi_debugpanel_icons_update(pid > 0 ? debug->state : 0);
|
_edi_debugpanel_icons_update(pid > 0 ? debug->state : 0);
|
||||||
|
|
||||||
return ECORE_CALLBACK_RENEW;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void edi_debugpanel_stop(void)
|
void edi_debugpanel_stop(void)
|
||||||
|
@ -322,7 +320,6 @@ void edi_debugpanel_add(Evas_Object *parent)
|
||||||
Evas_Object *ico_start, *ico_quit, *ico_int, *ico_term;
|
Evas_Object *ico_start, *ico_quit, *ico_int, *ico_term;
|
||||||
Elm_Code_Widget *widget;
|
Elm_Code_Widget *widget;
|
||||||
Elm_Code *code;
|
Elm_Code *code;
|
||||||
Ecore_Timer *timer;
|
|
||||||
|
|
||||||
frame = elm_frame_add(parent);
|
frame = elm_frame_add(parent);
|
||||||
elm_object_text_set(frame, _("Debug"));
|
elm_object_text_set(frame, _("Debug"));
|
||||||
|
@ -409,9 +406,6 @@ void edi_debugpanel_add(Evas_Object *parent)
|
||||||
|
|
||||||
edi_debug_new();
|
edi_debug_new();
|
||||||
|
|
||||||
timer = ecore_timer_add(1.0, _edi_debug_active_check_cb, NULL);
|
|
||||||
(void) timer;
|
|
||||||
|
|
||||||
elm_box_pack_end(box, widget);
|
elm_box_pack_end(box, widget);
|
||||||
elm_box_pack_end(box, table);
|
elm_box_pack_end(box, table);
|
||||||
evas_object_show(box);
|
evas_object_show(box);
|
||||||
|
|
|
@ -47,6 +47,14 @@ void edi_debugpanel_start(const char *toolname);
|
||||||
*/
|
*/
|
||||||
void edi_debugpanel_stop();
|
void edi_debugpanel_stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a poll to check the state of any debug session
|
||||||
|
*
|
||||||
|
* @ingroup UI
|
||||||
|
*/
|
||||||
|
void edi_debugpanel_active_check(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "edi_theme.h"
|
#include "edi_theme.h"
|
||||||
#include "edi_filepanel.h"
|
#include "edi_filepanel.h"
|
||||||
#include "edi_file.h"
|
#include "edi_file.h"
|
||||||
|
#include "edi_process.h"
|
||||||
#include "edi_logpanel.h"
|
#include "edi_logpanel.h"
|
||||||
#include "edi_consolepanel.h"
|
#include "edi_consolepanel.h"
|
||||||
#include "edi_searchpanel.h"
|
#include "edi_searchpanel.h"
|
||||||
|
@ -52,12 +53,64 @@ static Elm_Object_Item *_edi_selected_bottompanel;
|
||||||
static Evas_Object *_edi_filepanel, *_edi_filepanel_icon;
|
static Evas_Object *_edi_filepanel, *_edi_filepanel_icon;
|
||||||
|
|
||||||
static Evas_Object *_edi_menu_undo, *_edi_menu_redo, *_edi_toolbar_undo, *_edi_toolbar_redo, *_edi_toolbar_build, *_edi_toolbar_test;
|
static Evas_Object *_edi_menu_undo, *_edi_menu_redo, *_edi_toolbar_undo, *_edi_toolbar_redo, *_edi_toolbar_build, *_edi_toolbar_test;
|
||||||
static Evas_Object *_edi_menu_build, *_edi_menu_clean, *_edi_menu_test;
|
static Evas_Object *_edi_menu_build, *_edi_menu_clean, *_edi_menu_test, *_edi_menu_run, *_edi_menu_terminate;
|
||||||
static Evas_Object *_edi_menu_init, *_edi_menu_commit, *_edi_menu_push, *_edi_menu_pull, *_edi_menu_status, *_edi_menu_stash;
|
static Evas_Object *_edi_menu_init, *_edi_menu_commit, *_edi_menu_push, *_edi_menu_pull, *_edi_menu_status, *_edi_menu_stash;
|
||||||
static Evas_Object *_edi_menu_save, *_edi_toolbar_save;
|
static Evas_Object *_edi_menu_save, *_edi_toolbar_save;
|
||||||
static Evas_Object *_edi_main_win, *_edi_main_box;
|
static Evas_Object *_edi_main_win, *_edi_main_box;
|
||||||
|
static Evas_Object *_edi_toolbar_run, *_edi_toolbar_terminate;
|
||||||
int _edi_log_dom = -1;
|
int _edi_log_dom = -1;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_edi_active_process_icons_set(Eina_Bool active)
|
||||||
|
{
|
||||||
|
if (active)
|
||||||
|
{
|
||||||
|
elm_object_disabled_set(_edi_toolbar_run, EINA_TRUE);
|
||||||
|
elm_object_disabled_set(_edi_toolbar_terminate, EINA_FALSE);
|
||||||
|
elm_object_item_disabled_set(_edi_menu_run, EINA_TRUE);
|
||||||
|
elm_object_item_disabled_set(_edi_menu_terminate, EINA_FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
elm_object_disabled_set(_edi_toolbar_run, EINA_FALSE);
|
||||||
|
elm_object_disabled_set(_edi_toolbar_terminate, EINA_TRUE);
|
||||||
|
elm_object_item_disabled_set(_edi_menu_run, EINA_FALSE);
|
||||||
|
elm_object_item_disabled_set(_edi_menu_terminate, EINA_TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_edi_active_process_check_cb(EINA_UNUSED void *data)
|
||||||
|
{
|
||||||
|
Edi_Proc_Stats *stats;
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
// Check debugpanel state.
|
||||||
|
edi_debugpanel_active_check();
|
||||||
|
|
||||||
|
pid = edi_exe_project_pid_get();
|
||||||
|
if (pid == -1)
|
||||||
|
{
|
||||||
|
_edi_active_process_icons_set(EINA_FALSE);
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
stats = edi_process_stats_by_pid(pid);
|
||||||
|
if (!stats)
|
||||||
|
{
|
||||||
|
// Our process is not running, reset PID we
|
||||||
|
// track.
|
||||||
|
edi_exe_project_pid_reset();
|
||||||
|
_edi_active_process_icons_set(EINA_FALSE);
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stats);
|
||||||
|
|
||||||
|
_edi_active_process_icons_set(EINA_TRUE);
|
||||||
|
|
||||||
|
return ECORE_CALLBACK_RENEW;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_file_open_cb(const char *path, const char *type, Eina_Bool newwin)
|
_edi_file_open_cb(const char *path, const char *type, Eina_Bool newwin)
|
||||||
|
@ -722,6 +775,15 @@ _edi_launcher_run(Edi_Project_Config_Launch *launch)
|
||||||
edi_builder_run(launch->path, launch->args);
|
edi_builder_run(launch->path, launch->args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_edi_launcher_terminate(void)
|
||||||
|
{
|
||||||
|
pid_t pid = edi_exe_project_pid_get();
|
||||||
|
if (pid == -1) return;
|
||||||
|
|
||||||
|
kill(pid, SIGKILL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_build_menu_items_disabled_set(Eina_Bool state)
|
_edi_build_menu_items_disabled_set(Eina_Bool state)
|
||||||
{
|
{
|
||||||
|
@ -831,6 +893,12 @@ _tb_debug_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_i
|
||||||
_edi_debug_project();
|
_edi_debug_project();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tb_terminate_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||||
|
{
|
||||||
|
_edi_launcher_terminate();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_tb_about_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
_tb_about_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
@ -1037,6 +1105,13 @@ _edi_menu_run_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
||||||
_edi_launcher_run(&_edi_project_config->launch);
|
_edi_launcher_run(&_edi_project_config->launch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_edi_menu_terminate_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
||||||
|
void *event_info EINA_UNUSED)
|
||||||
|
{
|
||||||
|
_edi_launcher_terminate();
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_edi_menu_clean_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
_edi_menu_clean_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
|
||||||
void *event_info EINA_UNUSED)
|
void *event_info EINA_UNUSED)
|
||||||
|
@ -1227,9 +1302,11 @@ _edi_menu_setup(Evas_Object *win)
|
||||||
menu_it = elm_menu_item_add(menu, NULL, NULL, _("Build"), NULL, NULL);
|
menu_it = elm_menu_item_add(menu, NULL, NULL, _("Build"), NULL, NULL);
|
||||||
_edi_menu_build = elm_menu_item_add(menu, menu_it, "system-run", _("Build"), _edi_menu_build_cb, NULL);
|
_edi_menu_build = elm_menu_item_add(menu, menu_it, "system-run", _("Build"), _edi_menu_build_cb, NULL);
|
||||||
_edi_menu_test = elm_menu_item_add(menu, menu_it, "media-record", _("Test"), _edi_menu_test_cb, NULL);
|
_edi_menu_test = elm_menu_item_add(menu, menu_it, "media-record", _("Test"), _edi_menu_test_cb, NULL);
|
||||||
elm_menu_item_add(menu, menu_it, "media-playback-start", _("Run"), _edi_menu_run_cb, NULL);
|
|
||||||
_edi_menu_clean = elm_menu_item_add(menu, menu_it, "edit-clear", _("Clean"), _edi_menu_clean_cb, NULL);
|
_edi_menu_clean = elm_menu_item_add(menu, menu_it, "edit-clear", _("Clean"), _edi_menu_clean_cb, NULL);
|
||||||
elm_menu_item_separator_add(menu, menu_it);
|
elm_menu_item_separator_add(menu, menu_it);
|
||||||
|
_edi_menu_run = elm_menu_item_add(menu, menu_it, "media-playback-start", _("Run"), _edi_menu_run_cb, NULL);
|
||||||
|
_edi_menu_terminate = elm_menu_item_add(menu, menu_it, "media-playback-stop", _("Terminate"), _edi_menu_terminate_cb, NULL);
|
||||||
|
elm_menu_item_separator_add(menu, menu_it);
|
||||||
elm_menu_item_add(menu, menu_it, "utilities-terminal", _("Debugger"), _edi_menu_debug_cb, NULL);
|
elm_menu_item_add(menu, menu_it, "utilities-terminal", _("Debugger"), _edi_menu_debug_cb, NULL);
|
||||||
elm_menu_item_add(menu, menu_it, "applications-electronics", _("Memcheck"), _edi_menu_memcheck_cb, NULL);
|
elm_menu_item_add(menu, menu_it, "applications-electronics", _("Memcheck"), _edi_menu_memcheck_cb, NULL);
|
||||||
|
|
||||||
|
@ -1304,7 +1381,10 @@ edi_toolbar_setup(Evas_Object *parent)
|
||||||
|
|
||||||
_edi_toolbar_build = _edi_toolbar_item_add(tb, "system-run", _("Build"), _tb_build_cb);
|
_edi_toolbar_build = _edi_toolbar_item_add(tb, "system-run", _("Build"), _tb_build_cb);
|
||||||
_edi_toolbar_test = _edi_toolbar_item_add(tb, "media-record", _("Test"), _tb_test_cb);
|
_edi_toolbar_test = _edi_toolbar_item_add(tb, "media-record", _("Test"), _tb_test_cb);
|
||||||
_edi_toolbar_item_add(tb, "media-playback-start", _("Run"), _tb_run_cb);
|
tb_it = elm_toolbar_item_append(tb, "separator", "", NULL, NULL);
|
||||||
|
elm_toolbar_item_separator_set(tb_it, EINA_TRUE);
|
||||||
|
_edi_toolbar_run =_edi_toolbar_item_add(tb, "media-playback-start", _("Run"), _tb_run_cb);
|
||||||
|
_edi_toolbar_terminate = _edi_toolbar_item_add(tb, "media-playback-stop", _("Terminate"), _tb_terminate_cb);
|
||||||
_edi_toolbar_item_add(tb, "utilities-terminal", _("Debug"), _tb_debug_cb);
|
_edi_toolbar_item_add(tb, "utilities-terminal", _("Debug"), _tb_debug_cb);
|
||||||
|
|
||||||
tb_it = elm_toolbar_item_append(tb, "separator", "", NULL, NULL);
|
tb_it = elm_toolbar_item_append(tb, "separator", "", NULL, NULL);
|
||||||
|
@ -1581,6 +1661,7 @@ edi_open(const char *inputpath)
|
||||||
ecore_event_handler_add(EDI_EVENT_TAB_CHANGED, _edi_tab_changed, NULL);
|
ecore_event_handler_add(EDI_EVENT_TAB_CHANGED, _edi_tab_changed, NULL);
|
||||||
ecore_event_handler_add(EDI_EVENT_FILE_CHANGED, _edi_file_changed, NULL);
|
ecore_event_handler_add(EDI_EVENT_FILE_CHANGED, _edi_file_changed, NULL);
|
||||||
ecore_event_handler_add(EDI_EVENT_FILE_SAVED, _edi_file_saved, NULL);
|
ecore_event_handler_add(EDI_EVENT_FILE_SAVED, _edi_file_saved, NULL);
|
||||||
|
ecore_timer_add(1.0, _edi_active_process_check_cb, NULL);
|
||||||
|
|
||||||
ERR("Loaded project at %s", path);
|
ERR("Loaded project at %s", path);
|
||||||
evas_object_resize(win, _edi_project_config->gui.width * elm_config_scale_get(),
|
evas_object_resize(win, _edi_project_config->gui.width * elm_config_scale_get(),
|
||||||
|
|
|
@ -26,7 +26,7 @@ _relative_path_exists(const char *base, const char *relative)
|
||||||
static void
|
static void
|
||||||
_exec_cmd(const char *cmd)
|
_exec_cmd(const char *cmd)
|
||||||
{
|
{
|
||||||
ecore_exe_pipe_run(cmd,
|
edi_exe_project_run(cmd,
|
||||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||||
|
|
|
@ -76,7 +76,7 @@ _cmake_run(const char *path, const char *args)
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
{
|
||||||
ecore_exe_pipe_run(path, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
edi_exe_project_run(path, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ _cmake_run(const char *path, const char *args)
|
||||||
full_cmd = malloc(sizeof(char) * (full_len + 1));
|
full_cmd = malloc(sizeof(char) * (full_len + 1));
|
||||||
snprintf(full_cmd, full_len + 2, "%s %s", path, args);
|
snprintf(full_cmd, full_len + 2, "%s %s", path, args);
|
||||||
|
|
||||||
ecore_exe_pipe_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
edi_exe_project_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||||
|
|
||||||
|
|
|
@ -69,22 +69,40 @@ _go_test(void)
|
||||||
static void
|
static void
|
||||||
_go_run(const char *path EINA_UNUSED, const char *args EINA_UNUSED)
|
_go_run(const char *path EINA_UNUSED, const char *args EINA_UNUSED)
|
||||||
{
|
{
|
||||||
|
const char *ext;
|
||||||
char *full_cmd;
|
char *full_cmd;
|
||||||
int full_len;
|
int full_len, flags;
|
||||||
|
|
||||||
if (!path) return;
|
if (!path) return;
|
||||||
|
|
||||||
if (chdir(edi_project_get()) !=0)
|
if (chdir(edi_project_get()) !=0)
|
||||||
ERR("Could not chdir");
|
ERR("Could not chdir");
|
||||||
|
|
||||||
full_len = strlen(path) + 8;
|
full_len = strlen(path) + 8;
|
||||||
if (args)
|
if (args)
|
||||||
full_len += strlen(args);
|
full_len += strlen(args);
|
||||||
full_cmd = malloc(sizeof(char) * (full_len + 1));
|
|
||||||
snprintf(full_cmd, full_len + 1, "go run %s %s", path, args?args:"");
|
|
||||||
|
|
||||||
ecore_exe_pipe_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
full_cmd = malloc(sizeof(char) * (full_len + 1));
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
flags = ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
|
ECORE_EXE_PIPE_WRITE;
|
||||||
|
|
||||||
|
ext = strrchr(path, '.');
|
||||||
|
|
||||||
|
// We may want to run a binary or via the go command.
|
||||||
|
// Simple and quicker to test for file extension.
|
||||||
|
if (ext && !strcasecmp(ext, ".go"))
|
||||||
|
{
|
||||||
|
snprintf(full_cmd, full_len + 1, "go run %s %s", path, args?args:"");
|
||||||
|
flags |= ECORE_EXE_USE_SH;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(full_cmd, full_len + 1, "%s", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
edi_exe_project_run(full_cmd, flags, NULL);
|
||||||
|
|
||||||
free(full_cmd);
|
free(full_cmd);
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,7 +143,7 @@ _make_run(const char *path, const char *args)
|
||||||
|
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
{
|
||||||
ecore_exe_pipe_run(path, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
edi_exe_project_run(path, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ _make_run(const char *path, const char *args)
|
||||||
full_cmd = malloc(sizeof(char) * (full_len + 1));
|
full_cmd = malloc(sizeof(char) * (full_len + 1));
|
||||||
snprintf(full_cmd, full_len + 1, "%s %s", path, args);
|
snprintf(full_cmd, full_len + 1, "%s %s", path, args);
|
||||||
|
|
||||||
ecore_exe_pipe_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
edi_exe_project_run(full_cmd, ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,8 @@ _meson_run(const char *path, const char *args)
|
||||||
|
|
||||||
if (args) cmd = eina_slstr_printf("%s %s", path, args);
|
if (args) cmd = eina_slstr_printf("%s %s", path, args);
|
||||||
else cmd = path;
|
else cmd = path;
|
||||||
ecore_exe_pipe_run(cmd,
|
|
||||||
|
edi_exe_project_run(cmd,
|
||||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE /*| ECORE_EXE_USE_SH*/, md);
|
ECORE_EXE_PIPE_WRITE /*| ECORE_EXE_USE_SH*/, md);
|
||||||
|
|
|
@ -26,7 +26,7 @@ _relative_path_exists(const char *base, const char *relative)
|
||||||
static void
|
static void
|
||||||
_exec_cmd(const char *cmd)
|
_exec_cmd(const char *cmd)
|
||||||
{
|
{
|
||||||
ecore_exe_pipe_run(cmd,
|
edi_exe_project_run(cmd,
|
||||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_READ |
|
||||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR |
|
||||||
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
ECORE_EXE_PIPE_WRITE | ECORE_EXE_USE_SH, NULL);
|
||||||
|
|
|
@ -184,3 +184,29 @@ edi_exe_response(const char *command)
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static pid_t _project_pid = -1;
|
||||||
|
|
||||||
|
void
|
||||||
|
edi_exe_project_pid_reset()
|
||||||
|
{
|
||||||
|
_project_pid = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
edi_exe_project_pid_get(void)
|
||||||
|
{
|
||||||
|
return _project_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
edi_exe_project_run(const char *command, int flags, void *data)
|
||||||
|
{
|
||||||
|
Ecore_Exe *exe;
|
||||||
|
|
||||||
|
exe = ecore_exe_pipe_run(command, flags, data);
|
||||||
|
|
||||||
|
_project_pid = ecore_exe_pid_get(exe);
|
||||||
|
|
||||||
|
return _project_pid;
|
||||||
|
}
|
||||||
|
|
|
@ -62,6 +62,31 @@ EAPI void edi_exe_notify(const char *name, const char *command);
|
||||||
*/
|
*/
|
||||||
EAPI Eina_Bool edi_exe_notify_handle(const char *name, void ((*func)(int, void *)), void *data);
|
EAPI Eina_Bool edi_exe_notify_handle(const char *name, void ((*func)(int, void *)), void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function launches the project application binary. Used for monitoring a running
|
||||||
|
* process state. It's a wrapper for ecore_exe_run but is necessary to keep track of any
|
||||||
|
* instance of program being ran.
|
||||||
|
*
|
||||||
|
* @param command The command to execute.
|
||||||
|
* @param flags The ECORE_EXE flags to execute with.
|
||||||
|
* @param data Data to be passed to ecore_exe_run.
|
||||||
|
*
|
||||||
|
* @return PID of the process after executing.
|
||||||
|
*/
|
||||||
|
EAPI pid_t edi_exe_project_run(const char *command, int flags, void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the PID of the project executable if running.
|
||||||
|
*
|
||||||
|
* @return PID if the process exists else -1.
|
||||||
|
*/
|
||||||
|
EAPI pid_t edi_exe_project_pid_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the project PID to inactive state.
|
||||||
|
*/
|
||||||
|
EAPI void edi_exe_project_pid_reset(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
|
# define __MacOS__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MacOS__) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||||
|
# include <sys/types.h>
|
||||||
|
# include <sys/sysctl.h>
|
||||||
|
# include <sys/user.h>
|
||||||
|
# include <sys/proc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
# include <kvm.h>
|
||||||
|
# include <limits.h>
|
||||||
|
# include <sys/proc.h>
|
||||||
|
# include <sys/param.h>
|
||||||
|
# include <sys/resource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MacOS__)
|
||||||
|
# include <libproc.h>
|
||||||
|
# include <sys/proc_info.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "edi_process.h"
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <Ecore.h>
|
||||||
|
#include <Ecore_File.h>
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
_process_state_name(char state)
|
||||||
|
{
|
||||||
|
const char *statename = NULL;
|
||||||
|
#if defined(__linux__)
|
||||||
|
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 'D':
|
||||||
|
statename = "DSLEEP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
statename = "IDLE";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'R':
|
||||||
|
statename = "RUN";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'S':
|
||||||
|
statename = "SLEEP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
case 't':
|
||||||
|
statename = "STOP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'X':
|
||||||
|
statename = "DEAD";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Z':
|
||||||
|
statename = "ZOMB";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case SIDL:
|
||||||
|
statename = "IDLE";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SRUN:
|
||||||
|
statename = "RUN";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSLEEP:
|
||||||
|
statename = "SLEEP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SSTOP:
|
||||||
|
statename = "STOP";
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if !defined(__MacOS__)
|
||||||
|
#if !defined(__OpenBSD__)
|
||||||
|
case SWAIT:
|
||||||
|
statename = "WAIT";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SLOCK:
|
||||||
|
statename = "LOCK";
|
||||||
|
break;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
case SZOMB:
|
||||||
|
statename = "ZOMB";
|
||||||
|
break;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
case SDEAD:
|
||||||
|
statename = "DEAD";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SONPROC:
|
||||||
|
statename = "ONPROC";
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return statename;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
_parse_line(const char *line)
|
||||||
|
{
|
||||||
|
char *p, *tok;
|
||||||
|
|
||||||
|
p = strchr(line, ':') + 1;
|
||||||
|
while (isspace(*p))
|
||||||
|
p++;
|
||||||
|
tok = strtok(p, " ");
|
||||||
|
|
||||||
|
return atol(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
Edi_Proc_Stats *
|
||||||
|
edi_process_stats_by_pid(int pid)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char line[4096];
|
||||||
|
char state, program_name[1024];
|
||||||
|
int res, dummy, utime, stime, cutime, cstime, uid, psr, ppid;
|
||||||
|
unsigned int mem_size, mem_rss, pri, nice, numthreads;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/proc/%d/stat", pid);
|
||||||
|
if (!ecore_file_exists(path))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
f = fopen(path, "r");
|
||||||
|
if (!f) return NULL;
|
||||||
|
|
||||||
|
if (fgets(line, sizeof(line), f))
|
||||||
|
{
|
||||||
|
char *end, *start = strchr(line, '(') + 1;
|
||||||
|
end = strchr(line, ')');
|
||||||
|
strncpy(program_name, start, end - start);
|
||||||
|
program_name[end - start] = '\0';
|
||||||
|
|
||||||
|
res = sscanf(end + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d %d %d %d %u %d %d %d %d %d %d %d %d %d",
|
||||||
|
&state, &ppid, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &utime, &stime, &cutime, &cstime,
|
||||||
|
&pri, &nice, &numthreads, &dummy, &dummy, &mem_size, &mem_rss, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy,
|
||||||
|
&dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &psr, &dummy, &dummy, &dummy, &dummy, &dummy);
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if (res != 42) return NULL;
|
||||||
|
|
||||||
|
snprintf(path, sizeof(path), "/proc/%d/status", pid);
|
||||||
|
|
||||||
|
f = fopen(path, "r");
|
||||||
|
if (!f) return NULL;
|
||||||
|
|
||||||
|
while ((fgets(line, sizeof(line), f)) != NULL)
|
||||||
|
{
|
||||||
|
if (!strncmp(line, "Uid:", 4))
|
||||||
|
{
|
||||||
|
uid = _parse_line(line);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
Edi_Proc_Stats *p = calloc(1, sizeof(Edi_Proc_Stats));
|
||||||
|
p->pid = pid;
|
||||||
|
p->ppid = ppid;
|
||||||
|
p->uid = uid;
|
||||||
|
p->cpu_id = psr;
|
||||||
|
snprintf(p->command, sizeof(p->command), "%s", program_name);
|
||||||
|
p->state = _process_state_name(state);
|
||||||
|
p->cpu_time = utime + stime;
|
||||||
|
p->mem_size = mem_size;
|
||||||
|
p->mem_rss = mem_rss * getpagesize();
|
||||||
|
p->priority = pri;
|
||||||
|
p->nice = nice;
|
||||||
|
p->numthreads = numthreads;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__)
|
||||||
|
|
||||||
|
Edi_Proc_Stats *
|
||||||
|
edi_process_stats_by_pid(int pid)
|
||||||
|
{
|
||||||
|
struct kinfo_proc *kp;
|
||||||
|
kvm_t *kern;
|
||||||
|
char errbuf[4096];
|
||||||
|
int count, pagesize, pid_count;
|
||||||
|
|
||||||
|
kern = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf);
|
||||||
|
if (!kern) return NULL;
|
||||||
|
|
||||||
|
kp = kvm_getprocs(kern, KERN_PROC_PID, pid, sizeof(*kp), &count);
|
||||||
|
if (!kp) return NULL;
|
||||||
|
|
||||||
|
if (count == 0) return NULL;
|
||||||
|
pagesize = getpagesize();
|
||||||
|
|
||||||
|
Edi_Proc_Stats *p = malloc(sizeof(Edi_Proc_Stats));
|
||||||
|
p->pid = kp->p_pid;
|
||||||
|
p->ppid = kp->p_ppid;
|
||||||
|
p->uid = kp->p_uid;
|
||||||
|
p->cpu_id = kp->p_cpuid;
|
||||||
|
snprintf(p->command, sizeof(p->command), "%s", kp->p_comm);
|
||||||
|
p->state = _process_state_name(kp->p_stat);
|
||||||
|
p->cpu_time = kp->p_uticks + kp->p_sticks + kp->p_iticks;
|
||||||
|
p->mem_size = (kp->p_vm_tsize * pagesize) + (kp->p_vm_dsize * pagesize) + (kp->p_vm_ssize * pagesize);
|
||||||
|
p->mem_rss = kp->p_vm_rssize * pagesize;
|
||||||
|
p->priority = kp->p_priority - PZERO;
|
||||||
|
p->nice = kp->p_nice - NZERO;
|
||||||
|
p->numthreads = -1;
|
||||||
|
|
||||||
|
kp = kvm_getprocs(kern, KERN_PROC_SHOW_THREADS, 0, sizeof(*kp), &pid_count);
|
||||||
|
|
||||||
|
for (int i = 0; i < pid_count; i++)
|
||||||
|
{
|
||||||
|
if (kp[i].p_pid == p->pid)
|
||||||
|
p->numthreads++;
|
||||||
|
}
|
||||||
|
|
||||||
|
kvm_close(kern);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MacOS__)
|
||||||
|
Edi_Proc_Stats *
|
||||||
|
edi_process_stats_by_pid(int pid)
|
||||||
|
{
|
||||||
|
struct kinfo_proc kp;
|
||||||
|
struct proc_taskallinfo taskinfo;
|
||||||
|
struct proc_workqueueinfo workqueue;
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
size = proc_pidinfo(pid, PROC_PIDTASKALLINFO, 0, &taskinfo, sizeof(taskinfo));
|
||||||
|
if (size != sizeof(taskinfo))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size = proc_pidinfo(pid, PROC_PIDWORKQUEUEINFO, 0, &workqueue, sizeof(workqueue));
|
||||||
|
if (size != sizeof(workqueue))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Edi_Proc_Stats *p = calloc(1, sizeof(Edi_Proc_Stats));
|
||||||
|
p->pid = pid;
|
||||||
|
p->ppid = taskinfo.pbsd.pbi_ppid;
|
||||||
|
p->uid = taskinfo.pbsd.pbi_uid;
|
||||||
|
p->cpu_id = workqueue.pwq_nthreads;
|
||||||
|
snprintf(p->command, sizeof(p->command), "%s", taskinfo.pbsd.pbi_comm);
|
||||||
|
p->cpu_time = taskinfo.ptinfo.pti_total_user + taskinfo.ptinfo.pti_total_system;
|
||||||
|
p->cpu_time /= 10000000;
|
||||||
|
p->state = _process_state_name(taskinfo.pbsd.pbi_status);
|
||||||
|
p->mem_size = taskinfo.ptinfo.pti_virtual_size;
|
||||||
|
p->mem_rss = taskinfo.ptinfo.pti_resident_size;
|
||||||
|
p->priority = taskinfo.ptinfo.pti_priority;
|
||||||
|
p->nice = taskinfo.pbsd.pbi_nice;
|
||||||
|
p->numthreads = taskinfo.ptinfo.pti_threadnum;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||||
|
Edi_Proc_Stats *
|
||||||
|
edi_process_stats_by_pid(int pid)
|
||||||
|
{
|
||||||
|
struct rusage *usage;
|
||||||
|
struct kinfo_proc kp;
|
||||||
|
int mib[4];
|
||||||
|
size_t len;
|
||||||
|
int pagesize = getpagesize();
|
||||||
|
|
||||||
|
len = sizeof(int);
|
||||||
|
if (sysctlnametomib("kern.proc.pid", mib, &len) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
mib[3] = pid;
|
||||||
|
|
||||||
|
len = sizeof(kp);
|
||||||
|
if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Edi_Proc_Stats *p = calloc(1, sizeof(Edi_Proc_Stats));
|
||||||
|
p->pid = kp.ki_pid;
|
||||||
|
p->ppid = kp.ki_ppid;
|
||||||
|
p->uid = kp.ki_uid;
|
||||||
|
snprintf(p->command, sizeof(p->command), "%s", kp.ki_comm);
|
||||||
|
p->cpu_id = kp.ki_oncpu;
|
||||||
|
if (p->cpu_id == -1)
|
||||||
|
p->cpu_id = kp.ki_lastcpu;
|
||||||
|
|
||||||
|
usage = &kp.ki_rusage;
|
||||||
|
|
||||||
|
p->cpu_time = (usage->ru_utime.tv_sec * 1000000) + usage->ru_utime.tv_usec + (usage->ru_stime.tv_sec * 1000000) + usage->ru_stime.tv_usec;
|
||||||
|
p->cpu_time /= 10000;
|
||||||
|
p->state = _process_state_name(kp.ki_stat);
|
||||||
|
p->mem_size = kp.ki_size;
|
||||||
|
p->mem_rss = kp.ki_rssize * pagesize;
|
||||||
|
p->nice = kp.ki_nice = NZERO;
|
||||||
|
p->priority = kp.ki_pri.pri_level - PZERO;
|
||||||
|
p->numthreads = kp.ki_numthreads;
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
#ifndef __EDI_PROCESS_H__
|
||||||
|
#define __EDI_PROCESS_H__
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Routines for querying processes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Querying Processes
|
||||||
|
* @defgroup Proc
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* Query processes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#if !defined(PID_MAX)
|
||||||
|
# define PID_MAX 99999
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CMD_NAME_MAX 8192
|
||||||
|
|
||||||
|
typedef struct _Edi_Proc_Stats
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
pid_t ppid;
|
||||||
|
uid_t uid;
|
||||||
|
int8_t nice;
|
||||||
|
int8_t priority;
|
||||||
|
int cpu_id;
|
||||||
|
int32_t numthreads;
|
||||||
|
int64_t mem_size;
|
||||||
|
int64_t mem_rss;
|
||||||
|
double cpu_usage;
|
||||||
|
char command[CMD_NAME_MAX];
|
||||||
|
const char *state;
|
||||||
|
|
||||||
|
long cpu_time;
|
||||||
|
} Edi_Proc_Stats;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query a process for its current state.
|
||||||
|
*
|
||||||
|
* @param pid The process ID to query.
|
||||||
|
*
|
||||||
|
* @return Pointer to object containing the process information or NULL if non-existent.
|
||||||
|
*/
|
||||||
|
Edi_Proc_Stats *edi_process_stats_by_pid(int pid);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endif
|
|
@ -17,6 +17,8 @@ src = files([
|
||||||
'edi_exe.h',
|
'edi_exe.h',
|
||||||
'edi_path.c',
|
'edi_path.c',
|
||||||
'edi_path.h',
|
'edi_path.h',
|
||||||
|
'edi_process.c',
|
||||||
|
'edi_process.h',
|
||||||
'edi_private.h',
|
'edi_private.h',
|
||||||
'edi_scm.c',
|
'edi_scm.c',
|
||||||
'edi_scm.h',
|
'edi_scm.h',
|
||||||
|
|
Loading…
Reference in New Issue