--- /lib/rcscripts/sh/rc-services.sh.orig 2004-11-09 10:11:43.000000000 -0600 +++ /lib/rcscripts/sh/rc-services.sh 2004-11-09 10:22:50.000000000 -0600 @@ -397,6 +397,69 @@ return 1 } +# bool begin_exclusive( service ) +# +# atomically marks the service as being executed +# use like this: +# +# if begion_exclusive myexclusive ; then +# whatever is in here can only be executed by one process +# end_exclusive myexclusive +# fi + +begin_service() +{ + [ "$START_CRITICAL" == "yes" ] && return 0 + + mkfifo "${svcdir}/exclusive/$1" &> /dev/null + return $? +} + +# void end_exclusive(service, exitcode) +# +# stops executing a exclusive region and +# wakes up anybody who is waiting for the exclusive region +# +end_service() +{ + local newname + + # if we are doing critical services, there is no fifo + + [ "$START_CRITICAL" == "yes" ] && return + + if [ -n "$2" ] ; then + echo "$2" > "${svcdir}/exitcodes/$1" + fi + + # move the fifo to a unique name so noone is waiting for it after we touch it + newname="$(mktemp "${svcdir}/exclusive/$1.XXXXXXXXXX")" + mv -f "${svcdir}/exclusive/$1" "${newname}" + + # wake up anybody that was waiting for the fifo + touch "${newname}" + + # We dont need the fifo anymore + rm -f "${newname}" +} + +# int wait_exclusive(service) + +wait_service() +{ + + local retval + + [ "$START_CRITICAL" == "yes" ] && return 0 + + # this will block until the fifo is touched. It is touched by calling end_exclusive + # if no begin_eclusive has being called or end_exclusive has already finished + # this will not block + cat "${svcdir}/exclusive/$1" 2> /dev/null + retval="$( cat "${svcdir}/exitcodes/$1")" + return "${retval}" +} + # int start_service(service) # # Start 'service' if it is not already running. @@ -406,21 +469,43 @@ [ -z "$1" ] && return 1 - if ! service_started "$1" - then - splash "svc_start" "$1" - - if is_fake_service "$1" "${SOFTLEVEL}" - then - mark_service_started "$1" - splash "svc_started" "$1" "0" - else - (. /sbin/runscript.sh "/etc/init.d/$1" start) - retval="$?" - splash "svc_started" "$1" "${retval}" - return "${retval}" - fi - fi + #critical services can not start in parallel and begin_service fails because + #we don't have write permition to ${svcdir} + # so if we are doing critical services, disable the parallel feature + + # if it is not currently running or we are doing critical services + if begin_service "$1" ; then + + + + if ! service_started "$1" + then + splash "svc_start" "$1" + if is_fake_service "$1" "${SOFTLEVEL}" + then + mark_service_started "$1" + splash "svc_started" "$1" "0" + end_service "$1" "0" + else + ( + + (. /sbin/runscript.sh "/etc/init.d/$1" start) + retval="$?" + splash "svc_started" "$1" "${retval}" + end_service "$1" "${retval}" + ) & + + # if startup is not parallel, or we are doing criticall services + if [ "${RC_PARALLEL_STARTUP}" != "yes" -o "$START_CRITICAL" == "yes" ] ; then + wait + fi + + fi + else + end_service "$1" + fi + fi + return 0 } @@ -471,6 +556,8 @@ mark_service_started() { [ -z "$1" ] && return 1 + echo "0" > "${svcdir}/exitcodes/$1" + ln -snf "/etc/init.d/$1" "${svcdir}/started/$1" return $? @@ -594,60 +681,12 @@ # Schedule 'service' for startup, in parallel if possible. # schedule_service_startup() { - local count=0 - local current_job= - - if [ "${RC_PARALLEL_STARTUP}" = "yes" ] + if ! iparallel "$1" then - set -m +b - - if [ "$(jobs | grep -c "Running")" -gt 0 ] - then - if [ "$(jobs | grep -c "Running")" -eq 1 ] - then - if [ -n "$(jobs)" ] - then - current_job="$(jobs | awk '/Running/ { print $4}')" - fi - - # Wait if we cannot start this service with the already running - # one (running one might start this one ...). - query_before "$1" "${current_job}" && wait - - elif [ "$(jobs | grep -c "Running")" -ge 2 ] - then - count="$(jobs | grep -c "Running")" - - # Wait until we have only one service running - while [ "${count}" -gt 1 ] - do - count="$(jobs | grep -c "Running")" - done - - if [ -n "$(jobs)" ] - then - current_job="$(jobs | awk '/Running/ { print $4}')" - fi - - # Wait if we cannot start this service with the already running - # one (running one might start this one ...). - query_before "$1" "${current_job}" && wait - fi - fi - - if iparallel "$1" - then - eval start_service "$1" \& - else - # Do not start with any service running if we cannot start - # this service in parallel ... -# wait - - start_service "$1" - fi - else - start_service "$1" + wait fi + + start_service "$1" # We do not need to check the return value here, as svc_{start,stop}() do # their own error handling ... --- /sbin/depscan.sh.orig 2004-11-09 10:11:43.000000000 -0600 +++ /sbin/depscan.sh 2004-11-09 10:12:33.000000000 -0600 @@ -13,7 +13,7 @@ fi fi -for x in softscripts snapshot options started +for x in softscripts snapshot options started exclusive exitcodes do if [ ! -d "${svcdir}/${x}" ] then --- /sbin/rc.orig 2004-11-09 10:11:43.000000000 -0600 +++ /sbin/rc 2004-11-09 10:21:44.000000000 -0600 @@ -417,6 +417,8 @@ splash "rc_init" "${argv1}" + export START_CRITICAL="yes" + # We do not want to break compatibility, so we do not fully integrate # these into /sbin/rc, but rather start them by hand ... for x in ${CRITICAL_SERVICES} @@ -440,6 +442,9 @@ splash "svc_started" "${x}" "0" done + + unset START_CRITICAL + # Check that $svcdir exists ... check_statedir "${svcdir}" --- /sbin/runscript.sh.orig 2004-11-09 10:11:43.000000000 -0600 +++ /sbin/runscript.sh 2004-11-09 10:20:36.000000000 -0600 @@ -265,36 +265,51 @@ for y in ${netservices} do mynetservice="${y##*/}" + start_service "${mynetservice}" + done + + elif [ "${x}" != "net" ] + then + start_service "${x}" + fi + done + + # wait for dependencies to finish + for x in ${startupservices} + do + if [ "${x}" = "net" -a "${NETSERVICE}" != "yes" ] + then + local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \ + $(dolisting "/etc/runlevels/${mylevel}/net.*")" - if ! service_started "${mynetservice}" - then - start_service "${mynetservice}" + for y in ${netservices} + do + mynetservice="${y##*/}" + + wait_service "${mynetservice}" - # A 'need' dependency is critical for startup - if [ "$?" -ne 0 ] && ineed -t "${myservice}" "${x}" >/dev/null + # A 'need' dependency is critical for startup + if [ "$?" -ne 0 ] && ineed -t "${myservice}" "${x}" >/dev/null + then + # Only worry about a net.* service if we do not have one + # up and running already, or if RC_NET_STRICT_CHECKING + # is set .... + if ! is_net_up then - # Only worry about a net.* service if we do not have one - # up and running already, or if RC_NET_STRICT_CHECKING - # is set .... - if ! is_net_up - then - startfail="yes" - fi + startfail="yes" fi fi done elif [ "${x}" != "net" ] then - if ! service_started "${x}" - then - start_service "${x}" + + wait_service "${x}" - # A 'need' dependacy is critical for startup - if [ "$?" -ne 0 ] && ineed -t "${myservice}" "${x}" >/dev/null - then - startfail="yes" - fi + # A 'need' dependacy is critical for startup + if [ "$?" -ne 0 ] && ineed -t "${myservice}" "${x}" >/dev/null + then + startfail="yes" fi fi done