From 2a65f7772dcc16ec4f6f16699da048837fa2c535 Mon Sep 17 00:00:00 2001 From: Radon Rosborough Date: Fri, 20 Aug 2021 20:55:41 -0700 Subject: [PATCH] [#97] Tear down exec commands properly --- system/res/sentinel.bash | 14 ++++++-- system/src/riju-system-privileged.c | 52 +++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/system/res/sentinel.bash b/system/res/sentinel.bash index a04076f..22ee901 100755 --- a/system/res/sentinel.bash +++ b/system/res/sentinel.bash @@ -36,12 +36,20 @@ while read -t2 -r cmdline; do stdout="/var/cache/riju/share/cmd-${uuid}-stdout" stderr="/var/cache/riju/share/cmd-${uuid}-stderr" status="/var/cache/riju/share/cmd-${uuid}-status" - mkfifo "${stdin}" "${stdout}" "${stderr}" "${status}" + live="/var/cache/riju/share/cmd-${uuid}-live" + mkfifo "${stdin}" "${stdout}" "${stderr}" "${status}" "${live}" ( set +e - runuser -u riju -- bash -c "exec ${maybe_pty:-} \"\$@\"" -- "${args[@]}" < "${stdin}" > "${stdout}" 2> "${stderr}" - echo "$?" > "${status}" + ( + runuser -u riju -- bash -c "exec ${maybe_pty:-} \"\$@\"" -- "${args[@]}" < "${stdin}" > "${stdout}" 2> "${stderr}" + echo "$?" + ) > "${status}" ) & + bg=$! + while kill -0 "$bg" 2>/dev/null; do + sleep 1 + echo "ping" 2>/dev/null || break + done > "${live}" & fi ;; *) diff --git a/system/src/riju-system-privileged.c b/system/src/riju-system-privileged.c index 49affb2..71fa582 100644 --- a/system/src/riju-system-privileged.c +++ b/system/src/riju-system-privileged.c @@ -119,12 +119,19 @@ char *parseImageHash(char *imageHash) char *timeout_msg; -void wait_alarm(int signum) +void sigalrm_die(int signum) { (void)signum; die(timeout_msg); } +void sigalrm_kill_parent(int signum) +{ + (void)signum; + kill(getppid(), SIGTERM); + exit(EXIT_FAILURE); +} + void session(char *uuid, char *lang, char *imageHash) { if (setvbuf(stdout, NULL, _IONBF, 0) != 0) @@ -252,7 +259,7 @@ void session(char *uuid, char *lang, char *imageHash) ts_10ms.tv_sec = 0; ts_10ms.tv_nsec = 1000 * 1000 * 10; timeout_msg = "container did not come up within 10 seconds"; - if (signal(SIGALRM, wait_alarm) == SIG_ERR) + if (signal(SIGALRM, sigalrm_die) == SIG_ERR) die("signal failed"); alarm(10); int fd; @@ -287,7 +294,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) if (setvbuf(stdout, NULL, _IONBF, 0) != 0) die("setvbuf failed"); char *share, *ctlFIFO, *stdinFIFO, *stdoutFIFO, *stderrFIFO, *statusFIFO, - *ctlCmd, *dataFIFO; + *liveFIFO, *ctlCmd, *dataFIFO; if (asprintf(&share, "/var/cache/riju/shares/%s", uuid) < 0) die("asprintf failed"); if (asprintf(&ctlFIFO, "%s/control", share) < 0) @@ -301,6 +308,8 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) die("asprintf failed"); if (asprintf(&statusFIFO, "%s/cmd-%s-status", share, procUUID) < 0) die("asprintf failed"); + if (asprintf(&liveFIFO, "%s/cmd-%s-live", share, procUUID) < 0) + die("asprintf failed"); int fd = open(ctlFIFO, O_WRONLY); if (fd < 0) die("open failed"); @@ -352,15 +361,24 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) exit(EXIT_FAILURE); dataFIFO = stderrFIFO; } else { - dataFIFO = statusFIFO; + pid = fork(); + if (pid < 0) + die("fork failed"); + else if (pid == 0) { + if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) + die("prctl failed"); + if (getppid() != orig_ppid) + exit(EXIT_FAILURE); + dataFIFO = liveFIFO; + } else { + dataFIFO = statusFIFO; + } } } } - if (dataFIFO != statusFIFO) { - if (signal(SIGALRM, wait_alarm) == SIG_ERR) - die("signal failed"); - alarm(1); - } + if (signal(SIGALRM, sigalrm_die) == SIG_ERR) + die("signal failed"); + alarm(1); while (1) { int mode = dataFIFO == stdinFIFO ? O_WRONLY : O_RDONLY; fd = open(dataFIFO, mode); @@ -403,7 +421,7 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) } if (len < 0) die("read failed"); - } else { + } else if (dataFIFO == statusFIFO) { if (close(STDIN_FILENO) < 0) die("close failed"); if (close(STDOUT_FILENO) < 0) @@ -422,6 +440,20 @@ void exec(char *uuid, int argc, char **cmdline, bool pty) if (*endptr != '\n') die("strtol failed"); exit(status); + } else if (dataFIFO == liveFIFO) { + char line[1024]; + int len; + timeout_msg = "container died"; + if (signal(SIGALRM, sigalrm_kill_parent) < 0) + die("signal failed"); + if (alarm(2) < 0) + die("alarm failed"); + while ((len = read(fd, line, 1024)) > 0) { + if (alarm(2) < 0) + die("alarm failed"); + } + if (len < 0) + die("read failed"); } }