Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --kill-on-exit option #97

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/cli/proot.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ static int handle_option_0(Tracee *tracee, const Cli *cli, const char *value UNU
return handle_option_i(tracee, cli, "0:0");
}

static int handle_option_kill_on_exit(Tracee *tracee, const Cli *cli UNUSED, const char *value UNUSED)
{
tracee->killall_on_exit = true;
return 0;
}

static int handle_option_v(Tracee *tracee, const Cli *cli UNUSED, const char *value)
{
int status;
Expand Down
11 changes: 11 additions & 0 deletions src/cli/proot.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ static int handle_option_0(Tracee *tracee, const Cli *cli, const char *value);
static int handle_option_i(Tracee *tracee, const Cli *cli, const char *value);
static int handle_option_R(Tracee *tracee, const Cli *cli, const char *value);
static int handle_option_S(Tracee *tracee, const Cli *cli, const char *value);
static int handle_option_kill_on_exit(Tracee *tracee, const Cli *cli, const char *value);

static int pre_initialize_bindings(Tracee *, const Cli *, size_t, char *const *, size_t);
static int post_initialize_exe(Tracee *, const Cli *, size_t, char *const *, size_t);
Expand Down Expand Up @@ -142,6 +143,16 @@ Copyright (C) 2014 STMicroelectronics, licensed under GPL v2 or later.",
.detail = "\tSome programs expect to be launched from a given directory but do\n\
\tnot perform any chdir by themselves. This option avoids the\n\
\tneed for running a shell and then entering the directory manually.",
},
{ .class = "Regular options",
.arguments = {
{ .name = "--kill-on-exit", .separator = '\0', .value = NULL },
{ .name = NULL, .separator = '\0', .value = NULL } },
.handler = handle_option_kill_on_exit,
.description = "Kill all processes on command exit.",
.detail = "\tWhen the executed command leaves orphean or detached processes\n\
\taround, proot waits until all processes possibly terminate. This option forces\n\
\tthe immediate termination of all tracee processes when the main command exits.",
},
{ .class = "Regular options",
.arguments = {
Expand Down
4 changes: 2 additions & 2 deletions src/tracee/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,13 @@ int handle_tracee_event(Tracee *tracee, int tracee_status)
if (WIFEXITED(tracee_status)) {
last_exit_status = WEXITSTATUS(tracee_status);
VERBOSE(tracee, 1, "pid %d: exited with status %d", pid, last_exit_status);
tracee->terminated = true;
terminate_tracee(tracee);
}
else if (WIFSIGNALED(tracee_status)) {
check_architecture(tracee);
VERBOSE(tracee, (int) (last_exit_status != -1),
"pid %d: terminated with signal %d", pid, WTERMSIG(tracee_status));
tracee->terminated = true;
terminate_tracee(tracee);
}
else if (WIFSTOPPED(tracee_status)) {
/* Don't use WSTOPSIG() to extract the signal
Expand Down
16 changes: 16 additions & 0 deletions src/tracee/tracee.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,22 @@ Tracee *get_tracee(const Tracee *current_tracee, pid_t pid, bool create)
return (create ? new_tracee(pid) : NULL);
}

/**
* Mark tracee as terminated and optionally take action.
*/
void terminate_tracee(Tracee *tracee)
{
tracee->terminated = true;

/* Case where the terminated tracee is marked
to kill all tracees on exit.
*/
if (tracee->killall_on_exit) {
VERBOSE(tracee, 1, "terminating all tracees on exit");
kill_all_tracees();
}
}

/**
* Free all tracees marked as terminated.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/tracee/tracee.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ typedef struct tracee {
* dedicated to terminated tracees instead. */
bool terminated;

/* Whether termination of this tracee implies an immediate kill
* of all tracees. */
bool killall_on_exit;

/* Parent of this tracee, NULL if none. */
struct tracee *parent;

Expand Down Expand Up @@ -266,6 +270,7 @@ extern Tracee *get_stopped_ptracee(const Tracee *ptracer, pid_t pid,
extern bool has_ptracees(const Tracee *ptracer, pid_t pid, word_t wait_options);
extern int new_child(Tracee *parent, word_t clone_flags);
extern Tracee *new_dummy_tracee(TALLOC_CTX *context);
extern void terminate_tracee(Tracee *tracee);
extern void free_terminated_tracees();
extern int swap_config(Tracee *tracee1, Tracee *tracee2);
extern void kill_all_tracees();
Expand Down
23 changes: 23 additions & 0 deletions tests/test-killexit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
if [ -z `which setsid` ]; then
exit 125
fi

cleanup() {
_code=$?
trap - INT TERM EXIT
[ ! -f "${tmpfile-}" ] || rm -f "$tmpfile"
exit $_code
}
trap cleanup INT TERM EXIT

tmpfile=`mktemp`

# Check that kill on exit option is recognized
${PROOT} --kill-on-exit true

# Check that detached sleep does not block proot
# I.e. in the file we must have "success" first, not "fail"
${PROOT} --kill-on-exit sh -c "setsid sh -c \"sleep 2; echo fail >>$tmpfile\" &"
echo "success" >>$tmpfile
read status <$tmpfile
[ "$status" = success ] || exit 1