nspawn: move container wait logic into wait_for_container()
Move the container wait logic into its own wait_for_container() function and add two status codes: CONTAINER_TERMINATED or CONTAINER_REBOOTED. The status will be stored in its argument, this way we handle: a) Return negative on failures. b) Return zero on success and set the status to either CONTAINER_REBOOTED or CONTAINER_TERMINATED. These status codes are used to terminate nspawn or loop again in case of CONTAINER_REBOOTED.
This commit is contained in:
parent
6b56a65123
commit
113cea802d
|
@ -92,6 +92,11 @@
|
|||
#include "seccomp-util.h"
|
||||
#endif
|
||||
|
||||
typedef enum ContainerStatus {
|
||||
CONTAINER_TERMINATED,
|
||||
CONTAINER_REBOOTED
|
||||
} ContainerStatus;
|
||||
|
||||
typedef enum LinkJournal {
|
||||
LINK_NO,
|
||||
LINK_AUTO,
|
||||
|
@ -2569,6 +2574,74 @@ static int change_uid_gid(char **_home) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 in case the container is being rebooted, has been shut
|
||||
* down or exited successfully. On failures a negative value is
|
||||
* returned.
|
||||
*
|
||||
* The status of the container "CONTAINER_TERMINATED" or
|
||||
* "CONTAINER_REBOOTED" will be saved in the container argument
|
||||
*/
|
||||
static int wait_for_container(pid_t pid, ContainerStatus *container) {
|
||||
int r;
|
||||
siginfo_t status;
|
||||
|
||||
r = wait_for_terminate(pid, &status);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
switch (status.si_code) {
|
||||
case CLD_EXITED:
|
||||
r = status.si_status;
|
||||
if (r == 0) {
|
||||
if (!arg_quiet)
|
||||
log_debug("Container %s exited successfully.",
|
||||
arg_machine);
|
||||
|
||||
*container = CONTAINER_TERMINATED;
|
||||
} else {
|
||||
log_error("Container %s failed with error code %i.",
|
||||
arg_machine, status.si_status);
|
||||
r = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLD_KILLED:
|
||||
if (status.si_status == SIGINT) {
|
||||
if (!arg_quiet)
|
||||
log_info("Container %s has been shut down.",
|
||||
arg_machine);
|
||||
|
||||
*container = CONTAINER_TERMINATED;
|
||||
r = 0;
|
||||
break;
|
||||
} else if (status.si_status == SIGHUP) {
|
||||
if (!arg_quiet)
|
||||
log_info("Container %s is being rebooted.",
|
||||
arg_machine);
|
||||
|
||||
*container = CONTAINER_REBOOTED;
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
/* CLD_KILLED fallthrough */
|
||||
|
||||
case CLD_DUMPED:
|
||||
log_error("Container %s terminated by signal %s.",
|
||||
arg_machine, signal_to_string(status.si_status));
|
||||
r = -1;
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("Container %s failed due to unknown reason.",
|
||||
arg_machine);
|
||||
r = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
_cleanup_free_ char *kdbus_domain = NULL, *device_path = NULL, *root_device = NULL, *home_device = NULL, *srv_device = NULL;
|
||||
|
@ -2747,8 +2820,8 @@ int main(int argc, char *argv[]) {
|
|||
assert_se(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
|
||||
|
||||
for (;;) {
|
||||
ContainerStatus container_status;
|
||||
int parent_ready_fd = -1, child_ready_fd = -1;
|
||||
siginfo_t status;
|
||||
eventfd_t x;
|
||||
|
||||
parent_ready_fd = eventfd(0, EFD_CLOEXEC);
|
||||
|
@ -3100,48 +3173,16 @@ int main(int argc, char *argv[]) {
|
|||
/* Redundant, but better safe than sorry */
|
||||
kill(pid, SIGKILL);
|
||||
|
||||
k = wait_for_terminate(pid, &status);
|
||||
r = wait_for_container(pid, &container_status);
|
||||
pid = 0;
|
||||
|
||||
if (k < 0) {
|
||||
if (r < 0) {
|
||||
r = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status.si_code == CLD_EXITED) {
|
||||
r = status.si_status;
|
||||
if (status.si_status != 0) {
|
||||
log_error("Container %s failed with error code %i.", arg_machine, status.si_status);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!arg_quiet)
|
||||
log_debug("Container %s exited successfully.", arg_machine);
|
||||
} else if (container_status == CONTAINER_TERMINATED)
|
||||
break;
|
||||
} else if (status.si_code == CLD_KILLED &&
|
||||
status.si_status == SIGINT) {
|
||||
|
||||
if (!arg_quiet)
|
||||
log_info("Container %s has been shut down.", arg_machine);
|
||||
r = 0;
|
||||
break;
|
||||
} else if (status.si_code == CLD_KILLED &&
|
||||
status.si_status == SIGHUP) {
|
||||
|
||||
if (!arg_quiet)
|
||||
log_info("Container %s is being rebooted.", arg_machine);
|
||||
continue;
|
||||
} else if (status.si_code == CLD_KILLED ||
|
||||
status.si_code == CLD_DUMPED) {
|
||||
|
||||
log_error("Container %s terminated by signal %s.", arg_machine, signal_to_string(status.si_status));
|
||||
r = EXIT_FAILURE;
|
||||
break;
|
||||
} else {
|
||||
log_error("Container %s failed due to unknown reason.", arg_machine);
|
||||
r = EXIT_FAILURE;
|
||||
break;
|
||||
}
|
||||
/* CONTAINER_REBOOTED, loop again */
|
||||
}
|
||||
|
||||
finish:
|
||||
|
|
Loading…
Reference in a new issue