Author: eelco
Date: Sun Mar 18 01:53:35 2012
New Revision: 33222
URL: https://nixos.org/websvn/nix/?rev=33222&sc=1
Log:
* Improved Upstart job handling in switch-to-configuration. It no
longer compares the current configuration to the previous
configuration, but instead compares the current Upstart state to the
intended state. Thus, if the switch script is interrupted, running
nixos-rebuild again will resume starting/stopping Upstart jobs where
the previous run left off.
We determine if an Upstart job has changed by having the pre-start
script of each Upstart job put a symlink to its .conf file in
/var/run/upstart-jobs. So if this symlink differs from the target
of /etc/init/<job>.conf, then the job has changed. This also
prevents multiple restarts of dependent jobs. E.g., if job B has
"start on started A" and "stop on stopping A", then restarting A
will cause B to be restarted, so B shouldn't B restarted a second
time.
We only start jobs that are not running if 1) they're tasks that
have been previously run (like mountall); or 2) they're jobs that
have a "start on" condition. This seems a reasonable heuristic.
Modified:
nixos/trunk/modules/system/activation/activation-script.nix
nixos/trunk/modules/system/activation/switch-to-configuration.sh
nixos/trunk/modules/system/upstart/upstart.nix
Modified: nixos/trunk/modules/system/activation/activation-script.nix
==============================================================================
--- nixos/trunk/modules/system/activation/activation-script.nix Sun Mar 18
01:44:20 2012 (r33221)
+++ nixos/trunk/modules/system/activation/activation-script.nix Sun Mar 18
01:53:35 2012 (r33222)
@@ -109,6 +109,11 @@
mkdir -m 0755 -p /var/run/nix/current-load # for distributed builds
mkdir -m 0700 -p /var/run/nix/remote-stores
+ # Directory holding symlinks to currently running Upstart
+ # jobs. Used to determine which jobs need to be restarted
+ # when switching to a new configuration.
+ mkdir -m 0700 -p /var/run/upstart-jobs
+
mkdir -m 0755 -p /var/log
mkdir -m 0755 -p /var/log/upstart
Modified: nixos/trunk/modules/system/activation/switch-to-configuration.sh
==============================================================================
--- nixos/trunk/modules/system/activation/switch-to-configuration.sh Sun Mar
18 01:44:20 2012 (r33221)
+++ nixos/trunk/modules/system/activation/switch-to-configuration.sh Sun Mar
18 01:53:35 2012 (r33222)
@@ -62,75 +62,95 @@
fi
# Activate the new configuration.
-if [ "$action" = "switch" -o "$action" = "test" ]; then
+if [ "$action" != switch -a "$action" != test ]; then exit 0; fi
- oldVersion=$(cat /var/run/current-system/upstart-interface-version 2>
/dev/null || echo 0)
- newVersion=$(cat @out@/upstart-interface-version 2> /dev/null || echo 0)
+oldVersion=$(cat /var/run/current-system/upstart-interface-version 2>
/dev/null || echo 0)
+newVersion=$(cat @out@/upstart-interface-version 2> /dev/null || echo 0)
- if test "$oldVersion" -ne "$newVersion"; then
+if test "$oldVersion" -ne "$newVersion"; then
cat <<EOF
Warning: the new NixOS configuration has an Upstart version that is
incompatible with the current version. The new configuration won't
take effect until you reboot the system.
EOF
exit 1
- fi
+fi
- oldJobs=$(readlink -f /etc/static/init)
- newJobs=$(readlink -f @out@/etc/init)
+newJobs=$(readlink -f @out@/etc/init)
- stopJob() {
- local job=$1
+# Stop all currently running jobs that are not in the new Upstart
+# configuration. (Here "running" means all jobs that are not in the
+# stop/waiting state.)
+for job in $(initctl list | sed -e '/ stop\/waiting/ d; /^[^a-z]/ d; s/^\([^
]\+\).*/\1/' | sort); do
+ if ! [ -e "$newJobs/$job.conf" ] ; then
+ echo "stopping obsolete job ‘$job’..."
initctl stop "$job" || true
- }
+ fi
+done
- # Stop all services that are not in the new Upstart
- # configuration.
- for job in $(cd $oldJobs && ls *.conf); do
- job=$(basename $job .conf)
- if ! test -e "$newJobs/$job.conf"; then
- echo "stopping $job..."
- stopJob $job
- fi
- done
-
- # Activate the new configuration (i.e., update /etc, make
- # accounts, and so on).
- echo "activating the configuration..."
- @out@/activate @out@
-
- # Make Upstart reload its jobs.
- initctl reload-configuration
-
- # Start all new services and restart all changed services.
- for job in $(cd $newJobs && ls *.conf); do
-
- job=$(basename $job .conf)
-
- # Hack: skip the shutdown and control-alt-delete jobs.
- # Another hack: don't restart the X server (that would kill all the
clients).
- # And don't restart dbus, since that causes ConsoleKit to
- # forget about current sessions.
- # Idem for the emergeny-shell, because its `console owner'
- # line screws up the X server.
- # Idem for xendomains because we don't want to save/restore
- # Xen domains unless we have to.
- # TODO: Jobs should be able to declare that they should not be
- # auto-restarted.
- if echo "$job" | grep -q
"^shutdown$\|^control-alt-delete$\|^xserver$\|^dbus$\|^disnix$\|^emergency-shell$\|^xendomains$\|^udevtrigger$\|^drbd-down$";
then continue; fi
-
- if ! test -e "$oldJobs/$job.conf"; then
- echo "starting $job..."
- initctl start "$job" || true
- elif test "$(readlink "$oldJobs/$job.conf")" != "$(readlink
"$newJobs/$job.conf")"; then
- echo "restarting $job..."
- stopJob $job
- initctl start "$job" || true
- fi
- done
-
- # Signal dbus to reload its configuration.
- dbusPid=$(initctl status dbus 2> /dev/null | sed -e 's/.*process
\([0-9]\+\)/\1/;t;d')
- [ -n "$dbusPid" ] && kill -HUP "$dbusPid"
+# Activate the new configuration (i.e., update /etc, make accounts,
+# and so on).
+echo "activating the configuration..."
+@out@/activate @out@
+
+# Make Upstart reload its jobs.
+initctl reload-configuration
+
+# Allow Upstart jobs to react intelligently to a config change.
+initctl emit config-changed
+
+# Restart all running jobs that have changed. (Here "running" means
+# all jobs that don't have a "stop" goal.) We use the symlinks in
+# /var/run/upstart-jobs (created by each job's pre-start script) to
+# determine if a job has changed.
+for job in $(cd $newJobs && ls *.conf); do
+ job=$(basename $job .conf)
+ status=$(status "$job")
+ if ! [[ "$status" =~ start/ ]]; then continue; fi
+ if [ "$(readlink -f "$newJobs/$job.conf")" = "$(readlink -f
"/var/run/upstart-jobs/$job")" ]; then continue; fi
+ # Hack: don't restart the X server (that would kill all the clients).
+ # And don't restart dbus, since that causes ConsoleKit to
+ # forget about current sessions.
+ # Idem for xendomains because we don't want to save/restore
+ # Xen domains unless we have to.
+ # TODO: Jobs should be able to declare that they should not be
+ # auto-restarted.
+ if echo "$job" | grep -q
"^xserver$\|^dbus$\|^disnix$\|^xendomains$\|^udevtrigger$"; then
+ echo "not restarting changed service ‘$job’"
+ continue
+ fi
+ echo "restarting changed service ‘$job’..."
+ # Note: can't use "restart" here, since that only restarts the
+ # job's main process.
+ stop "$job" || true
+ start "$job" || true
+done
+
+# Start all jobs that are not running but should be. The "should be"
+# criterion is tricky: the intended semantics is that we end up with
+# the same jobs as after a reboot. If it's a task, restart it if it
+# differs from the previous instance of the same task; if it wasn't
+# previously run, don't run it. If it's a service, only start it if
+# it has a "start on" condition.
+for job in $(cd $newJobs && ls *.conf); do
+ job=$(basename $job .conf)
+ status=$(status "$job")
+ if ! [[ "$status" =~ stop/ ]]; then continue; fi
+
+ if grep -q '^task$' "$newJobs/$job.conf"; then
+ if [ ! -e "/var/run/upstart-jobs/$job" -o \
+ "$(readlink -f "$newJobs/$job.conf")" = "$(readlink -f
"/var/run/upstart-jobs/$job")" ];
+ then continue; fi
+ echo "starting task ‘$job’..."
+ start "$job" || true
+ else
+ if ! grep -q "^start on" "$newJobs/$job.conf"; then continue; fi
+ echo "starting service ‘$job’..."
+ start "$job" || true
+ fi
-fi
+done
+
+# Signal dbus to reload its configuration.
+dbusPid=$(initctl status dbus 2> /dev/null | sed -e 's/.*process
\([0-9]\+\)/\1/;t;d')
+[ -n "$dbusPid" ] && kill -HUP "$dbusPid"
Modified: nixos/trunk/modules/system/upstart/upstart.nix
==============================================================================
--- nixos/trunk/modules/system/upstart/upstart.nix Sun Mar 18 01:44:20
2012 (r33221)
+++ nixos/trunk/modules/system/upstart/upstart.nix Sun Mar 18 01:53:35
2012 (r33222)
@@ -42,13 +42,14 @@
${concatMapStrings (n: "env ${n}=\"${getAttr n env}\"\n") (attrNames
env)}
- ${optionalString (job.preStart != "") ''
- pre-start script
- exec >> ${log} 2>&1
+ pre-start script
+ exec >> ${log} 2>&1
+ ln -sfn "$(readlink -f "/etc/init/${job.name}.conf")"
/var/run/upstart-jobs/${job.name}
+ ${optionalString (job.preStart != "") ''
source ${jobHelpers}
${job.preStart}
- end script
- ''}
+ ''}
+ end script
${if job.script != "" && job.exec != "" then
abort "Job ${job.name} has both a `script' and `exec' attribute."
_______________________________________________
nix-commits mailing list
[email protected]
http://lists.science.uu.nl/mailman/listinfo/nix-commits