[Pkg-sysvinit-devel] parallel startup does not work?

Sebastian Pöhn s.poehn at stud.hs-esslingen.de
Fri May 11 10:26:29 UTC 2012


Hi sysvinit maintainers!

I am doing a student research project on benchmarking common init systems
on Linux. I use Debian a test system for LSB/insserv/startpar/sysvinit.
Somehow the CONCURRENCY=makefile and startpar boot does not work as
expected.

That's what I have in my /etc/rc2.d/ (I enter this runlevel):
-rw-r--r-- 1 root root 677 Mär 13 08:14 README
lrwxrwxrwx 1 root root  19 Apr 30 14:06 S01dummy_fs1 -> ../init.d/dummy_fs1
lrwxrwxrwx 1 root root  19 Apr 30 14:09 S01dummy_fs2 -> ../init.d/dummy_fs2
lrwxrwxrwx 1 root root  19 Apr 30 14:10 S01dummy_fs3 -> ../init.d/dummy_fs3
lrwxrwxrwx 1 root root  19 Apr 30 14:10 S01dummy_fs4 -> ../init.d/dummy_fs4
lrwxrwxrwx 1 root root  19 Apr 30 14:10 S01dummy_fs5 -> ../init.d/dummy_fs5
lrwxrwxrwx 1 root root  20 Apr 30 14:29 S01dummy_net1 -> ../init.d/dummy_net1
lrwxrwxrwx 1 root root  20 Apr 30 14:29 S01dummy_net2 -> ../init.d/dummy_net2
lrwxrwxrwx 1 root root  20 Apr 30 14:29 S01dummy_net3 -> ../init.d/dummy_net3
lrwxrwxrwx 1 root root  20 Apr 30 14:29 S01dummy_net4 -> ../init.d/dummy_net4
lrwxrwxrwx 1 root root  20 Apr 30 14:29 S01dummy_net5 -> ../init.d/dummy_net5
lrwxrwxrwx 1 root root  21 Apr 30 14:29 S01dummy_udev1 ->
../init.d/dummy_udev1
lrwxrwxrwx 1 root root  21 Apr 30 14:29 S01dummy_udev2 ->
../init.d/dummy_udev2
lrwxrwxrwx 1 root root  21 Apr 30 14:29 S01dummy_udev3 ->
../init.d/dummy_udev3
lrwxrwxrwx 1 root root  21 Apr 30 14:29 S01dummy_udev4 ->
../init.d/dummy_udev4
lrwxrwxrwx 1 root root  21 Apr 30 14:29 S01dummy_udev5 ->
../init.d/dummy_udev5
lrwxrwxrwx 1 root root  17 Apr 16 10:07 S15rpcbind -> ../init.d/rpcbind
lrwxrwxrwx 1 root root  20 Apr 16 10:07 S16nfs-common -> ../init.d/nfs-common
lrwxrwxrwx 1 root root  24 Apr 16 10:08 S18binfmt-support ->
../init.d/binfmt-support
lrwxrwxrwx 1 root root  17 Apr 16 10:07 S18rsyslog -> ../init.d/rsyslog
lrwxrwxrwx 1 root root  14 Apr 16 10:08 S18sudo -> ../init.d/sudo
lrwxrwxrwx 1 root root  14 Apr 16 10:26 S19acct -> ../init.d/acct
lrwxrwxrwx 1 root root  15 Apr 16 10:07 S19acpid -> ../init.d/acpid
lrwxrwxrwx 1 root root  17 Apr 16 10:08 S19anacron -> ../init.d/anacron
lrwxrwxrwx 1 root root  13 Apr 16 10:07 S19atd -> ../init.d/atd
lrwxrwxrwx 1 root root  14 Apr 16 10:07 S19cron -> ../init.d/cron
lrwxrwxrwx 1 root root  14 Apr 16 10:07 S19dbus -> ../init.d/dbus
lrwxrwxrwx 1 root root  15 Apr 16 10:07 S19exim4 -> ../init.d/exim4
lrwxrwxrwx 1 root root  20 Apr 16 10:08 S19kerneloops -> ../init.d/kerneloops
lrwxrwxrwx 1 root root  21 Apr 16 10:08 S19loadcpufreq ->
../init.d/loadcpufreq
lrwxrwxrwx 1 root root  20 Apr 16 10:08 S19pulseaudio -> ../init.d/pulseaudio
lrwxrwxrwx 1 root root  22 Apr 16 10:08 S20avahi-daemon ->
../init.d/avahi-daemon
lrwxrwxrwx 1 root root  19 Apr 16 10:07 S20bluetooth -> ../init.d/bluetooth
lrwxrwxrwx 1 root root  22 Apr 16 10:08 S20cpufrequtils ->
../init.d/cpufrequtils
lrwxrwxrwx 1 root root  21 Apr 30 14:28 S20dummy_dbus1 ->
../init.d/dummy_dbus1
lrwxrwxrwx 1 root root  21 Apr 30 14:28 S20dummy_dbus2 ->
../init.d/dummy_dbus2
lrwxrwxrwx 1 root root  21 Apr 30 14:28 S20dummy_dbus3 ->
../init.d/dummy_dbus3
lrwxrwxrwx 1 root root  21 Apr 30 14:28 S20dummy_dbus4 ->
../init.d/dummy_dbus4
lrwxrwxrwx 1 root root  21 Apr 30 14:28 S20dummy_dbus5 ->
../init.d/dummy_dbus5
lrwxrwxrwx 1 root root  25 Apr 16 10:07 S20network-manager ->
../init.d/network-manager
lrwxrwxrwx 1 root root  14 Apr 16 10:08 S21cups -> ../init.d/cups
lrwxrwxrwx 1 root root  14 Apr 16 10:08 S21gdm3 -> ../init.d/gdm3
lrwxrwxrwx 1 root root  15 Apr 16 10:08 S21saned -> ../init.d/saned
lrwxrwxrwx 1 root root  18 Apr 16 10:08 S22bootlogs -> ../init.d/bootlogs
lrwxrwxrwx 1 root root  19 Apr 16 10:26 S23bootchart -> ../init.d/bootchart
lrwxrwxrwx 1 root root  19 Apr 16 10:08 S23minissdpd -> ../init.d/minissdpd
lrwxrwxrwx 1 root root  18 Apr 16 10:08 S23rc.local -> ../init.d/rc.local
lrwxrwxrwx 1 root root  19 Apr 16 10:08 S23rmnologin -> ../init.d/rmnologin

So insserv did its job right, most dummy services are capable of parallel
starting(same number = parallel). The "no_prune.png" shows that this
services are not runt in parallel! "bootchart.png" is like I would have
expected (I changed 3 lines in the startup function with
CONCURRENCY=none).

So is this a bug in startpar or is this behaviour correct?

Greetings
Sebastian Pöhn
University of Applied Sciences Esslingen

---
startpar version 0.58
Linux debian 3.2.0-2-amd64 #1 SMP Fri Apr 6 05:01:55 UTC 2012 x86_64
GNU/Linux

/etc/init.d/rc:
#! /bin/sh
#
# rc
#
# Starts/stops services on runlevel changes.
#
# Optimization: A start script is not run when the service was already
# configured to run in the previous runlevel.  A stop script is not run
# when the the service was already configured not to run in the previous
# runlevel.
#
# Authors:
# 	Miquel van Smoorenburg <miquels at cistron.nl>
# 	Bruce Perens <Bruce at Pixar.com>

PATH=/sbin:/usr/sbin:/bin:/usr/bin
export PATH

# Un-comment the following for interactive debugging. Do not un-comment
# this for debugging a real boot process as no scripts will be executed.
# debug=echo

# Specify method used to enable concurrent init.d scripts.
# Valid options are 'none' and 'makefile'.  Obsolete options
# used earlier are 'shell' and 'startpar'.  The obsolete options
# are aliases for 'makefile' since 2010-05-14.  The default since
# the same date is 'makefile', as the init.d scripts in Debian now
# include dependency information and are ordered using this
# information.  See insserv for information on dependency based
# boot sequencing.
CONCURRENCY=makefile

# Make sure the name survive changing the argument list
scriptname="$0"

umask 022

on_exit() {
	echo "error: '$scriptname' exited outside the expected code flow."
}
trap on_exit EXIT # Enable emergency handler

# Ignore CTRL-C only in this shell, so we can interrupt subprocesses.
trap ":" INT QUIT TSTP

# Set onlcr to avoid staircase effect.
stty onlcr 0>&1

# Now find out what the current and what the previous runlevel are.

runlevel=$RUNLEVEL
# Get first argument. Set new runlevel to this argument.
[ "$1" != "" ] && runlevel=$1
if [ "$runlevel" = "" ]
then
	echo "Usage: $scriptname <runlevel>" >&2
	exit 1
fi
previous=$PREVLEVEL
[ "$previous" = "" ] && previous=N

export runlevel previous

if [ -f /etc/default/rcS ] ; then
	. /etc/default/rcS
fi
export VERBOSE

if [ -f /lib/lsb/init-functions ] ; then
	. /lib/lsb/init-functions
else
	log_action_msg() { echo $@; }
	log_failure_msg() { echo $@; }
	log_warning_msg() { echo $@; }
fi

#
# Check if we are able to use make like booting.  It require the
# insserv package to be enabled. Boot concurrency also requires
# startpar to be installed.
#
if [ "none" != "$CONCURRENCY" ] ; then
	test -s /etc/init.d/.depend.boot  || CONCURRENCY="none"
	test -s /etc/init.d/.depend.start || CONCURRENCY="none"
	test -s /etc/init.d/.depend.stop  || CONCURRENCY="none"
	if test -e /etc/init.d/.legacy-bootordering ; then
		CONCURRENCY="none"
	fi
	startpar -v      > /dev/null 2>&1 || CONCURRENCY="none"
fi

#
# Start script or program.
#
case "$CONCURRENCY" in
	makefile|startpar|shell) # startpar and shell are obsolete
		CONCURRENCY=makefile
		log_action_msg "Using makefile-style concurrent boot in runlevel $runlevel"
		startup() {
			eval "$(startpar -p 4 -t 20 -T 3 -M $1 -P $previous -R $runlevel)"

			if [ -n "$failed_service" ]
			then
				log_failure_msg "startpar: service(s) returned failure: $failed_service"
			fi

			if [ -n "$skipped_service" ]
			then
				log_warning_msg "startpar: service(s) skipped: $skipped_service"
			fi

			unset failed_service skipped_service
		}
		;;
	none|*)
		startup() {
			action=$1
			shift
			scripts="$@"
			for script in $scripts ; do
				$debug "$script" $action
			done
		}
		;;
esac

# Is there an rc directory for this new runlevel?
if [ -d /etc/rc$runlevel.d ]
then
	case "$runlevel" in
		0|6)
			ACTION=stop
			;;
		S)
			ACTION=start
			;;
		*)
			ACTION=start
			;;
	esac

	# First, run the KILL scripts.
	if [ makefile = "$CONCURRENCY" ]
	then
		if [ "$ACTION" = "start" ] && [ "$previous" != N ]
		then
			startup stop
		fi
	elif [ "$previous" != N ]
	then
		# Run all scripts with the same level in parallel
		CURLEVEL=""
		for s in /etc/rc$runlevel.d/K*
		do
			# Extract order value from symlink
			level=${s#/etc/rc$runlevel.d/K}
			level=${level%%[a-zA-Z]*}
			if [ "$level" = "$CURLEVEL" ]
			then
				continue
			fi
			CURLEVEL=$level
			SCRIPTS=""
			for i in /etc/rc$runlevel.d/K$level*
			do
				# Check if the script is there.
				[ ! -f $i ] && continue

				#
				# Find stop script in previous runlevel but
				# no start script there.
				#
				suffix=${i#/etc/rc$runlevel.d/K[0-9][0-9]}
				previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
				previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
				#
				# If there is a stop script in the previous level
				# and _no_ start script there, we don't
				# have to re-stop the service.
				#
				[ -f $previous_stop ] && [ ! -f $previous_start ] && continue

				# Stop the service.
				SCRIPTS="$SCRIPTS $i"
			done
			startup stop $SCRIPTS
		done
	fi

	if [ makefile = "$CONCURRENCY" ]
	then
		if [ S = "$runlevel" ]
		then
			startup boot
		else
			startup $ACTION
		fi
	else
		# Now run the START scripts for this runlevel.
		# Run all scripts with the same level in parallel
		CURLEVEL=""
		for s in /etc/rc$runlevel.d/S*
		do
			# Extract order value from symlink
			level=${s#/etc/rc$runlevel.d/S}
			level=${level%%[a-zA-Z]*}
			if [ "$level" = "$CURLEVEL" ]
			then
				continue
			fi
			CURLEVEL=$level
			SCRIPTS=""
			for i in /etc/rc$runlevel.d/S$level*
			do
				[ ! -f $i ] && continue

				suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}
				if [ "$previous" != N ]
				then
					#
					# Find start script in previous runlevel and
					# stop script in this runlevel.
					#
					stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix
					previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
					#
					# If there is a start script in the previous level
					# and _no_ stop script in this level, we don't
					# have to re-start the service.
					#
					if [ start = "$ACTION" ] ; then
						[ -f $previous_start ] && [ ! -f $stop ] && continue
					else
						# Workaround for the special
						# handling of runlevels 0 and 6.
						previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
						#
						# If there is a stop script in the previous level
						# and _no_ start script there, we don't
						# have to re-stop the service.
						#
						[ -f $previous_stop ] && [ ! -f $previous_start ] && continue
					fi

				fi
				SCRIPTS="$SCRIPTS $i"
			done
			startup $ACTION $SCRIPTS
		done
	fi
fi

trap - EXIT # Disable emergency handler

exit 0

/etc/default/rcS:
#
# /etc/default/rcS
#
# Default settings for the scripts in /etc/rcS.d/
#
# For information about these variables see the rcS(5) manual page.
#
# This file belongs to the "initscripts" package.

# delete files in /tmp during boot older than x days.
# '0' means always, -1 or 'infinite' disables the feature
TMPTIME=0

# spawn sulogin during boot, continue normal boot if not used in 30 seconds
SULOGIN=no

# do not allow users to log in until the boot has completed
DELAYLOGIN=no

# assume that the BIOS clock is set to UTC time (recommended)
UTC=yes

# be more verbose during the boot process
VERBOSE=no

# automatically repair filesystems with inconsistencies during boot
FSCKFIX=no

# mount /run/lock as a tmpfs (separately from /run)
RAMLOCK=yes

# mount /run/shm as a tmpfs (separately from /run)
RAMSHM=yes

# mount /tmp as a tmpfs
RAMTMP=yes

-------------- next part --------------
A non-text attachment was scrubbed...
Name: no_prune.png
Type: image/png
Size: 845180 bytes
Desc: not available
URL: <http://lists.alioth.debian.org/pipermail/pkg-sysvinit-devel/attachments/20120511/2863dfea/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: bootchart.png
Type: image/png
Size: 900696 bytes
Desc: not available
URL: <http://lists.alioth.debian.org/pipermail/pkg-sysvinit-devel/attachments/20120511/2863dfea/attachment-0003.png>


More information about the Pkg-sysvinit-devel mailing list