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

Gustavo Sverzut Barbieri barbieri at profusion.mobi
Tue Oct 5 22:11:16 PDT 2010


On Wed, Oct 6, 2010 at 2:05 AM, Gustavo Sverzut Barbieri
<barbieri at profusion.mobi> wrote:
> From: Fabiano Fidencio <fidencio at profusion.mobi>
>
> This functions are working as follows:
>    - Send a SIGTERM to all processes that may be finished
>    - Send a SIGKILL to all processes that still live and may be finished
>    - Try to unmount all mount points
>    - Try to remount read-only all mount points that can't be umounted
>    - Umount all swap devices
>    - Umount and detach all loopback devices
>    - Call [poweroff|halt|reboot|kexec]
>
> TODO:
>    - Umount device-mapper.
>    - Make log work. So far it is being useless as we do not parse
>      /etc/systemd/system.conf, kernel command line but just
>      environment, however we're executed by init and thus have no
>      useful variables. Forcing it to target=kmsg/console and
>      level=debug also does not produce any output, however writing to
>      /dev/console does work (hack used during debug).

This is a new version more correct than the first one as it ignore the
kernel threads, it will also handle cases where there are no child
left. The original code was always hitting the 5 seconds limit, making
it slow (at least 10 seconds to shutdown).

> +static bool is_kernel_thread(pid_t pid)
> +{
> +        char buf[PATH_MAX];
> +        FILE *f;
> +        char c;
> +        size_t count;
> +
> +        snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long)pid);
> +        f = fopen(buf, "re");
> +        if (!f)
> +                return true; /* not really, but has the desired effect */
> +
> +        count = fread(&c, 1, 1, f);
> +        fclose(f);
> +        return count != 1;
> +}
> +
> +static int killall(int sign) {
> +        DIR *dir;
> +        struct dirent *d;
> +        unsigned int processes = 0;
> +
> +        if ((dir = opendir("/proc")) == NULL)
> +                return -errno;
> +
> +        while ((d = readdir(dir))) {
> +                pid_t pid;
> +
> +                if (parse_pid(d->d_name, &pid) < 0)
> +                        continue;
> +
> +                if (is_kernel_thread(pid))
> +                        continue;
> +
> +                if (ignore_proc(pid))
> +                        continue;
> +
> +                if (kill(pid, sign) == 0)
> +                        processes++;
> +                else
> +                        pid = waitpid(-1, NULL, WNOHANG);
> +                        if (pid == 0)
> +                                break;
> +                        else if (pid < 0 && errno == ECHILD) {
> +                                processes = 0;
> +                                goto finish;
> +                        }


these are basically the difference. Please review and apply, ready to rock!

-- 
Gustavo Sverzut Barbieri
http://profusion.mobi embedded systems
--------------------------------------
MSN: barbieri at gmail.com
Skype: gsbarbieri
Mobile: +55 (19) 9225-2202


More information about the systemd-devel mailing list