Skip to content
Permalink
Browse files

REF: Replace kill_subtree code so it uses only pgrep (procps)

Avoids dependencies: bash, awk, coreutils, findutils.
Other approaches (e.g. libprocps or parsing /proc) aren't portable.
  • Loading branch information...
kernc committed Jan 20, 2019
1 parent 85325e8 commit 5fa6dba5e0436348950fd4d87c3116078d210718
Showing with 36 additions and 37 deletions.
  1. +35 −36 src/exec.c
  2. +1 −1 src/exec.h
@@ -9,14 +9,16 @@
static inline
int
execute (char **argv,
char **envp)
char **envp,
char **stdout)
{
g_autoptr (GError) err = NULL;
gint exit_status = -1;
GSpawnFlags flags = G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
GSpawnFlags flags = G_SPAWN_STDERR_TO_DEV_NULL |
(stdout ? G_SPAWN_DEFAULT : G_SPAWN_STDOUT_TO_DEV_NULL);

g_spawn_sync (NULL, argv, envp, flags | G_SPAWN_SEARCH_PATH,
NULL, NULL, NULL, NULL, &exit_status, &err);
NULL, NULL, stdout, NULL, &exit_status, &err);
if (err)
g_warning ("Unexpected subprocess execution error: %s", err->message);

@@ -43,7 +45,7 @@ xsus_exec_subprocess (char **argv,

// Execute and return result
g_debug ("Exec %#lx (%d): %s", entry->xid, entry->pid, argv[2]);
int exit_status = execute (argv, envp);
int exit_status = execute (argv, envp, NULL);
g_debug ("Exit status: %d", exit_status);

// Free envp
@@ -53,44 +55,41 @@ xsus_exec_subprocess (char **argv,
}


int
static
void
kill_recursive (char* pid_str, int signal, char* cmd_pattern)
{
// Kill the process
g_debug (" - %s", pid_str);
kill ((pid_t) g_ascii_strtoll (pid_str, NULL, 10), signal);

// Pgrep its children
char *argv[] = {"pgrep", "-fP", pid_str, cmd_pattern, NULL};
g_autofree char *standard_output = NULL;
execute (argv, NULL, &standard_output);
if (! standard_output)
return; // No children

// Recurse
g_auto (GStrv) child_pids = g_strsplit (g_strstrip (standard_output), "\n", 0);
for (int i = 0; child_pids[i]; ++i)
kill_recursive (child_pids[i], signal, cmd_pattern);
}


void
xsus_kill_subtree (pid_t pid,
int signal,
char *cmd_pattern)
{
if (! cmd_pattern)
return 0;
return;

g_assert (signal == SIGSTOP || signal == SIGCONT);
char *sig = signal == SIGSTOP ? "STOP" : "CONT";

// Prefer this short script to using pstree (induces extra dependency)
// or involved parsing of /proc
g_autofree char *script = g_strdup_printf (
"pid=%d\n"
"ps_output=\"$(ps -e -o ppid,pid,cmd | awk \"/%s/\"'{ print $1, $2 }')\"\n"
"while [ \"$pid\" ]; do\n"
" pid=\"$(echo \"$ps_output\" | awk \"/^($pid) /{ print \\$2 }\")\"\n"
" echo -n $pid\" \"\n"
" pid=\"$(echo \"$pid\" | paste -sd '|' -)\"\n"
"done%s | xargs kill -%s 2>/dev/null",
pid, cmd_pattern, (IS_DEBUG ? " | tee /dev/fd/2" : ""), sig);

char *argv[] = {
"sh", "-c", script, NULL};
char *envp[] = {
g_strdup_printf ("PATH=%s", g_getenv ("PATH")),
g_strdup_printf ("LC_ALL=C"), // Speeds up locale-aware awk
NULL
};

// Execute and return result
g_debug ("Exec: pstree %d | kill -%s", pid, sig);
int exit_status = execute (argv, envp);
g_debug ("Exit status: %d", exit_status);

// Free envp
char **e = envp; while (*e) g_free(*e++);

return exit_status;
g_debug ("Exec: pstree %d (%s) | kill -%s",
pid, cmd_pattern, signal == SIGSTOP ? "STOP" : "CONT");
char pid_str[11];
g_snprintf ((char*) &pid_str, sizeof (pid_str), "%d", pid);
kill_recursive (pid_str, signal, cmd_pattern);
}
@@ -7,6 +7,6 @@


int xsus_exec_subprocess (char **argv, WindowEntry *entry);
int xsus_kill_subtree (pid_t pid, int signal, char *cmd_pattern);
void xsus_kill_subtree (pid_t pid, int signal, char *cmd_pattern);

#endif // XSUSPENDER_SUBPROCESS_H

0 comments on commit 5fa6dba

Please sign in to comment.
You can’t perform that action at this time.