[systemd-devel] [PATCH 2/2] Adding binary to shutdown the system

Lennart Poettering lennart at poettering.net
Wed Oct 6 06:24:14 PDT 2010


On Wed, 06.10.10 02:05, Gustavo Sverzut Barbieri (barbieri at profusion.mobi) wrote:

> +static int send_signal(int sign) {
> +        sigset_t mask, oldmask;
> +        usec_t until;
> +        int processes;
> +        struct timespec ts;
> +
> +        sigemptyset(&mask);

Minor nitpick: I tend to enclose invocations like this with assert_se(x
== 0), e.g.

assert_se(sigemptyset(&mask) == 0);

This makes clear for the reader that there is is no realistic way this
could ever fail. But then again, this doesn't really matter.

> +        for (;;) {
> +                usec_t n;
> +
> +                for (;;) {
> +                        pid_t pid;
> +
> +                        n = now(CLOCK_MONOTONIC);
> +                        if (n >= until)
> +                                goto finish;

Put these two lines in the outer loop. There should be no need to query
the time each time.

> +static int rescue_send_signal(int sign) {
> +        sigset_t mask, oldmask;
> +        usec_t until;
> +        struct timespec ts;
> +        int r;
> +

Hmm, this  function does mostly the  same as send_signal()  but lets the
kernel iterate,  right? Given how similar  the functions I  wonder if it
would be nicer to use a bool argument to switch between the two modes...

> +int main(int argc, char *argv[]) {
> +        int cmd, r, retries;
> +        bool need_umount = true, need_swapoff = true, need_loop_detach = true;
> +
> +        log_parse_environment();
> +        log_set_target(LOG_TARGET_KMSG); /* syslog will die if not gone yet */
> +        log_open();

Hmm, if logging does not work for you, maybe you disabled kernel console
logging for debug messages? An option might be to raise the kernel log
level here?

> +
> +        if (getpid() != 1) {
> +                log_debug("only init may exec this binary");

I think this should be log_error(). Also, please use proper sentences,
i.e. uppercase the first char and add a full stop to the end.

> +                r = -EPERM;
> +                goto error;
> +        }
> +
> +        if (argc != 2) {
> +                log_debug("invalid number of arguments");

Siimilar here.

> +                r = -EINVAL;
> +                goto error;
> +        }
> +
> +        if (streq(argv[1], "reboot"))
> +                cmd = RB_AUTOBOOT;
> +        else if (streq(argv[1], "poweroff"))
> +                cmd = RB_POWER_OFF;
> +        else if (streq(argv[1], "halt"))
> +                cmd = RB_HALT_SYSTEM;
> +        else if (streq(argv[1], "kexec"))
> +                cmd = LINUX_REBOOT_CMD_KEXEC;
> +        else {
> +                log_debug("unknown action %s", argv[1]);
> +                r = -EINVAL;

And here.

> +        if (cmd == LINUX_REBOOT_CMD_KEXEC) {
> +                const char *args[5] = {KEXEC_BINARY_PATH, "-e", "-x", "-f", NULL};
> +                /* we cheat and exec kexec to avoid doing all its work */
> +                execv(args[0], (char * const *) args);
> +                log_warning("kexec not supported, falling back to reboot");
> +                cmd = RB_AUTOBOOT;
> +        }

Hmm, I wonder if we might need to fork things here... If we justz exec
kexec and it fails for some reason, is it capabale of invoking the
fallback reboot(RB_AUTOBOOT) itself? If it isn't we should fork off
kexec here, and wait for it, and if it fails do our own
reboot(RB_AUTOBOOT) instead.

Otherwise looks fantastic.

Lennart

-- 
Lennart Poettering - Red Hat, Inc.


More information about the systemd-devel mailing list