From 8cad533a762e777cd32783c4dd09b43ef072e04d Mon Sep 17 00:00:00 2001 From: Marc Weber Date: Fri, 6 Mar 2009 12:27:47 +0000 Subject: [PATCH] Convert "reboot/halt" events svn path=/nixos/branches/fix-style/; revision=14407 --- system/options.nix | 1 + upstart-jobs/default.nix | 9 -- upstart-jobs/halt.nix | 207 +++++++++++++++++++++------------------ 3 files changed, 113 insertions(+), 104 deletions(-) diff --git a/system/options.nix b/system/options.nix index 6b24af8309f..fdb224b6788 100644 --- a/system/options.nix +++ b/system/options.nix @@ -427,6 +427,7 @@ in (import ../upstart-jobs/nscd.nix) # Name service cache daemon. (import ../upstart-jobs/maintenance-shell.nix) # Handles the maintenance/stalled event (single-user shell). (import ../upstart-jobs/ctrl-alt-delete.nix) # Ctrl-alt-delete action. + (import ../upstart-jobs/halt.nix) # FIXME (assertion) # Handles the reboot/halt events. # security diff --git a/upstart-jobs/default.nix b/upstart-jobs/default.nix index 5db0ccdd5a5..85c5622bf4d 100644 --- a/upstart-jobs/default.nix +++ b/upstart-jobs/default.nix @@ -77,15 +77,6 @@ let inherit config; }) - # Handles the reboot/halt events. - ++ (map - (event: makeJob (import ../upstart-jobs/halt.nix { - inherit (pkgs) bash utillinux; - inherit event; - })) - ["reboot" "halt" "system-halt" "power-off"] - ) - # User-defined events. ++ (map makeJob (config.services.extraJobs)); diff --git a/upstart-jobs/halt.nix b/upstart-jobs/halt.nix index 9e6c798ea86..d98a3b5eea4 100644 --- a/upstart-jobs/halt.nix +++ b/upstart-jobs/halt.nix @@ -1,103 +1,120 @@ -{bash, event, utillinux}: +{pkgs, config, ...}: +###### implementation + + +/* FIXME assert event == "reboot" || event == "halt" || event == "system-halt" || event == "power-off"; +*/ + +let + + inherit (pkgs) bash utillinux; + + jobFun = event : { + name = "sys-" + event; + + job = '' + start on ${event} + + script + set +e # continue in case of errors + + exec < /dev/tty1 > /dev/tty1 2>&1 + echo "" + echo "<<< SYSTEM SHUTDOWN >>>" + echo "" + + export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH + + + # Set the hardware clock to the system time. + echo "Setting the hardware clock..." + hwclock --systohc --utc || true + + + # Do an initial sync just in case. + sync || true + + + # Kill all remaining processes except init and this one. + echo "Sending the TERM signal to all processes..." + kill -TERM -1 || true + + sleep 1 # wait briefly + + echo "Sending the KILL signal to all processes..." + kill -KILL -1 || true + + + # Unmount helper functions. + getMountPoints() { + cat /proc/mounts \ + | grep -v '^rootfs' \ + | sed 's|^[^ ]\+ \+\([^ ]\+\).*|\1|' \ + | grep -v '/proc\|/sys\|/dev' + } + + getDevice() { + local mountPoint=$1 + cat /proc/mounts \ + | grep -v '^rootfs' \ + | grep "^[^ ]\+ \+$mountPoint \+" \ + | sed 's|^\([^ ]\+\).*|\1|' + } + + # Unmount file systems. We repeat this until no more file systems + # can be unmounted. This is to handle loopback devices, file + # systems mounted on other file systems and so on. + tryAgain=1 + while test -n "$tryAgain"; do + tryAgain= + + for mp in $(getMountPoints); do + device=$(getDevice $mp) + echo "unmounting $mp..." + if umount -f -n "$mp"; then + if test "$mp" != /; then tryAgain=1; fi + else + mount -n -o remount,ro "$mp" || true + fi + + # Hack: work around a bug in mount (mount -o remount on a + # loop device forgets the loop=/dev/loopN entry in + # /etc/mtab). + if echo "$device" | grep -q '/dev/loop'; then + echo "removing loop device $device..." + losetup -d "$device" || true + fi + done + done + + cat /proc/mounts + + + # Final sync. + sync || true + + + # Right now all events above power off the system. + if test ${event} = reboot; then + exec reboot -f + else + exec halt -f -p + fi + + end script + ''; + }; + +in + { - name = "sys-" + event; - - job = " -start on ${event} - -script - set +e # continue in case of errors - - exec < /dev/tty1 > /dev/tty1 2>&1 - echo \"\" - echo \"<<< SYSTEM SHUTDOWN >>>\" - echo \"\" - - export PATH=${utillinux}/bin:${utillinux}/sbin:$PATH - - - # Set the hardware clock to the system time. - echo \"Setting the hardware clock...\" - hwclock --systohc --utc || true - - - # Do an initial sync just in case. - sync || true - - - # Kill all remaining processes except init and this one. - echo \"Sending the TERM signal to all processes...\" - kill -TERM -1 || true - - sleep 1 # wait briefly - - echo \"Sending the KILL signal to all processes...\" - kill -KILL -1 || true - - - # Unmount helper functions. - getMountPoints() { - cat /proc/mounts \\ - | grep -v '^rootfs' \\ - | sed 's|^[^ ]\\+ \\+\\([^ ]\\+\\).*|\\1|' \\ - | grep -v '/proc\\|/sys\\|/dev' - } - - getDevice() { - local mountPoint=$1 - cat /proc/mounts \\ - | grep -v '^rootfs' \\ - | grep \"^[^ ]\\+ \\+$mountPoint \\+\" \\ - | sed 's|^\\([^ ]\\+\\).*|\\1|' - } - - # Unmount file systems. We repeat this until no more file systems - # can be unmounted. This is to handle loopback devices, file - # systems mounted on other file systems and so on. - tryAgain=1 - while test -n \"$tryAgain\"; do - tryAgain= - - for mp in $(getMountPoints); do - device=$(getDevice $mp) - echo \"unmounting $mp...\" - if umount -f -n \"$mp\"; then - if test \"$mp\" != /; then tryAgain=1; fi - else - mount -n -o remount,ro \"$mp\" || true - fi - - # Hack: work around a bug in mount (mount -o remount on a - # loop device forgets the loop=/dev/loopN entry in - # /etc/mtab). - if echo \"$device\" | grep -q '/dev/loop'; then - echo \"removing loop device $device...\" - losetup -d \"$device\" || true - fi - done - done - - cat /proc/mounts - - - # Final sync. - sync || true - - - # Right now all events above power off the system. - if test ${event} = reboot; then - exec reboot -f - else - exec halt -f -p - fi - -end script - "; - + services = { + extraJobs = map jobFun ["reboot" "halt" "system-halt" "power-off"]; + }; }