diff options
author | Franck Bui <fbui@suse.com> | 2016-11-24 18:52:04 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2016-11-24 18:52:04 +0100 |
commit | acc28e2e3037d689d6481e4664925cf31d4d087b (patch) | |
tree | fd93ecff4ebff8690ec8da76f52020831bfbc5ba | |
parent | c495dfb9c38fd1944490f46b8e854f010aeaa238 (diff) |
core: make sure initrd-switch-root command survives PID1's killing spree (#4730)
This is a different way to implement the fix proposed by commit
a4021390fef27f4136497328f suggested by Lennart Poettering.
In this patch we instruct PID1 to not kill "systemctl switch-root" command
started by initrd-switch-root service using the "argv[0][0]='@'" trick.
See: https://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons/ for
more details.
We had to backup argv[0] because argv is modified by dispatch_verb().
-rw-r--r-- | src/systemctl/systemctl.c | 10 | ||||
-rw-r--r-- | units/initrd-switch-root.service.in | 8 |
2 files changed, 11 insertions, 7 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 4fd8d7ba27..ed1c7178b5 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -142,6 +142,7 @@ static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; static char *arg_root = NULL; static usec_t arg_when = 0; +static char *argv_cmdline = NULL; static enum action { _ACTION_INVALID, ACTION_SYSTEMCTL, @@ -5638,6 +5639,13 @@ static int switch_root(int argc, char *argv[], void *userdata) { init = NULL; } + /* Instruct PID1 to exclude us from its killing spree applied during + * the transition from the initrd to the main system otherwise we would + * exit with a failure status even though the switch to the new root + * has succeed. */ + if (in_initrd()) + argv_cmdline[0] = '@'; + r = acquire_bus(BUS_MANAGER, &bus); if (r < 0) return r; @@ -8373,6 +8381,8 @@ static int logind_cancel_shutdown(void) { int main(int argc, char*argv[]) { int r; + argv_cmdline = argv[0]; + setlocale(LC_ALL, ""); log_parse_environment(); log_open(); diff --git a/units/initrd-switch-root.service.in b/units/initrd-switch-root.service.in index b89f2348c7..82893dafb1 100644 --- a/units/initrd-switch-root.service.in +++ b/units/initrd-switch-root.service.in @@ -17,10 +17,4 @@ AllowIsolate=yes Type=oneshot # we have to use "--force" here, otherwise systemd would umount /run ExecStart=@rootbindir@/systemctl --no-block --force switch-root /sysroot - -# Just before switching to the new rootfs, systemd might send us a TERM signal -# depending on how fast we are to execute the main command and exit. If we get -# the SIGTERM signal that simply means that we succeed but haven't got enough -# time to exit properly. Since systemd considers SIGTERM as a failure for -# short-running process (aka Type=oneshot), instruct it to ignore this case. -SuccessExitStatus=SIGTERM +KillMode=none |