From c06b7a851f35dcb4495d7c0e7d3483317c40e350 Mon Sep 17 00:00:00 2001 From: David Walter Seikel Date: Sun, 1 Jan 2006 20:09:47 +0000 Subject: [PATCH] If you terminate an exe, make sure it really is terminated. Check it's pulse, hold a mirror to it's mouth, check for brain activity. Pump another round or two into it, cut off it's head, put a stake through it's heart. Sprinkle holy water over it's corpse, hold a black mass to ask Lucifer if it turned up in hell yet, consult the entrails of rasters three headed chicken. If all else fails, complain that the bitch is still alive, and stronger measures will be needed. SVN revision: 19475 --- legacy/ecore/src/lib/ecore/ecore_exe.c | 116 +++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/legacy/ecore/src/lib/ecore/ecore_exe.c b/legacy/ecore/src/lib/ecore/ecore_exe.c index 0cbd1162b3..7ad998e63c 100644 --- a/legacy/ecore/src/lib/ecore/ecore_exe.c +++ b/legacy/ecore/src/lib/ecore/ecore_exe.c @@ -6,11 +6,20 @@ #ifndef WIN32 +struct _ecore_exe_dead_exe +{ + pid_t pid; + char *cmd; +}; + static void _ecore_exe_exec_it(const char *exe_cmd); static int _ecore_exe_data_read_handler(void *data, Ecore_Fd_Handler *fd_handler); static int _ecore_exe_data_write_handler(void *data, Ecore_Fd_Handler *fd_handler); static void _ecore_exe_flush(Ecore_Exe *exe); static void _ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev); +static int _ecore_exe_is_it_alive(pid_t pid); +static int _ecore_exe_make_sure_its_dead(void *data); +static int _ecore_exe_make_sure_its_really_dead(void *data); static Ecore_Exe *exes = NULL; static char *shell = NULL; @@ -393,6 +402,7 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data) if (!ok) { /* Something went wrong, so pull down everything. */ + /* FIXME: should kill it if it managed to start up. */ IF_FN_DEL(_ecore_exe_free, exe); } else @@ -601,13 +611,24 @@ ecore_exe_continue(Ecore_Exe *exe) void ecore_exe_terminate(Ecore_Exe *exe) { + struct _ecore_exe_dead_exe *dead; + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) { ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate"); return; } + printf("Sending TERM signal to %s (%d).\n", exe->cmd, exe->pid); kill(exe->pid, SIGTERM); + + dead = calloc(1, sizeof(struct _ecore_exe_dead_exe)); + if (dead) + { + dead->pid = exe->pid; + dead->cmd = strdup(exe->cmd); + ecore_timer_add(10.0, _ecore_exe_make_sure_its_dead, dead); + } } /** @@ -618,13 +639,24 @@ ecore_exe_terminate(Ecore_Exe *exe) void ecore_exe_kill(Ecore_Exe *exe) { + struct _ecore_exe_dead_exe *dead; + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) { ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill"); return; } + printf("Sending KILL signal to %s (%d).\n", exe->cmd, exe->pid); kill(exe->pid, SIGKILL); + + dead = calloc(1, sizeof(struct _ecore_exe_dead_exe)); + if (dead) + { + dead->pid = exe->pid; + dead->cmd = strdup(exe->cmd); + ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead, dead); + } } /** @@ -666,6 +698,90 @@ ecore_exe_hup(Ecore_Exe *exe) kill(exe->pid, SIGHUP); } +static int +_ecore_exe_is_it_alive(pid_t pid) +{ + Ecore_Exe *exe; + + /* FIXME: There is no nice, safe, OS independant way to tell if a + * particular PID is still alive. I have written code to do so + * for my urunlevel busybox applet (http://urunlevel.sourceforge.net/), + * but it's for linux only, and still not guaranteed. + * + * So for now, we just check that a valid Ecore_Exe structure + * exists for it. Even that is not a guarantee, as the structure + * can be freed without killing the process. + * + * I think we can safely put exe's into two categories, those users + * that care about the life of the exe, and the run and forget type. + * The run and forget type starts up the exe, then free's the + * Ecore_Exe structure straight away. They can never call any of + * the functions that can call this, so we don't worry about them. + * + * Those user's that care about the life of exe's will keep the + * Ecore_Exe structure around, terminate them eventually, or + * register for exit events. For these ones the assumption + * that valid Ecore_Exe struct == live exe is almost valid. + * + * I will probably copy my urunlevel code into here someday. + */ + exe = _ecore_exe_find(pid); + if (exe) + { + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + return (pid_t) 1; + } + + return (pid_t) 0; +} + +static int +_ecore_exe_make_sure_its_dead(void *data) +{ + struct _ecore_exe_dead_exe *dead; + + dead = data; + if (dead) + { + if (_ecore_exe_is_it_alive(dead->pid)) + { + if (dead->cmd) + printf("Sending KILL signal to alledgedly dead %s (%d).\n", dead->cmd, dead->pid); + else + printf("Sending KILL signal to alledgedly dead PID %d.\n", dead->pid); + kill(dead->pid, SIGKILL); + ecore_timer_add(10.0, _ecore_exe_make_sure_its_really_dead, dead); + } + else + { + IF_FREE(dead->cmd); + free(dead); + } + } + return 0; +} + +static int +_ecore_exe_make_sure_its_really_dead(void *data) +{ + struct _ecore_exe_dead_exe *dead; + + dead = data; + if (dead) + { + if (_ecore_exe_is_it_alive(dead->pid)) + { + if (dead->cmd) + printf("%s (%d) is not really dead.\n", dead->cmd, dead->pid); + else + printf("PID %d is not really dead.\n", dead->pid); + } + IF_FREE(dead->cmd); + free(dead); + } + return 0; +} + void _ecore_exe_shutdown(void)