Package: dhcp-probe
Version: 1.3.0-5
Severity: important
Tags: patch

This box uses upstart.

The pid file directory /var/run/dhcp-probe does not exist.  That fixed,
success startup rate is not predictable, indeed :(

Either fails because the interface(s) are not fully configured:

        dhcp_probe[1307]: dhcp_probe: bad interface 'eth0': eth0: no IPv4 
address assigned

or because the daemon pid is not yet created:

        dhcp_probe[13534]: could not open pid file 
/var/run/dhcp-probe/dhcp_probe.pid.eth0 for writing

The attached patch corrects:

* the above mentioned errors
* typo bug 'start-start_daemon' in a couple of places
* removed useless quotes
* made code indentation consistent
* several more cleanups need to be done (see FIXME comments)
* debug code needs to be ripped off (see debug log attached)
* improved performance by removing several forks; it could be further
  improved
* general cleanups

-- System Information:
Debian Release: squeeze/sid
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'testing')
Architecture: i386 (i686)

Kernel: Linux 2.6.32-5-686 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages dhcp-probe depends on:
ii  libc6                         2.11.2-1   Embedded GNU C Library: Shared lib
ii  libnet1                       1.1.4-2    library for the construction and h
ii  libpcap0.8                    1.1.1-2    system interface for user-level pa
ii  net-tools                     1.60-23    The NET-3 networking toolkit
ii  ucf                           3.0025     Update Configuration File: preserv

dhcp-probe recommends no packages.

dhcp-probe suggests no packages.

-- no debconf information


Cheers,

-- 
Cristian
--- dhcp-probe.orig	2010-03-30 21:26:34.000000000 +0200
+++ dhcp-probe	2010-06-20 22:14:56.627200739 +0200
@@ -8,108 +8,135 @@
 # Short-Description: dhcp-probe daemon to survey DHCP/BootP server on LAN
 ### END INIT INFO
 
+set -e
+exec 2>/tmp/${0##*/}.debug
+set -x
 
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 DAEMON=/usr/sbin/dhcp_probe
-NAME="dhcp-probe"
-PIDFILE="dhcp_probe.pid"
-BASE_RUNNING="/var/run"
-BASEPIDFILE="$BASE_RUNNING/$NAME"
-INITPIDFILE="$BASEPIDFILE/$PIDFILE"
+LABEL=${DAEMON##*/}
+NAME=dhcp-probe
+PIDFILE=dhcp_probe.pid
+BASE_RUNNING=/var/run
+# FIXME: This is one confusing variable name!  It's not a file, but a dir!
+BASEPIDFILE=$BASE_RUNNING/$NAME
+INITPIDFILE=$BASEPIDFILE/$PIDFILE
 DESC="$NAME daemon"
-ETC="/etc"
-#DEFAULT="$ETC/default"
-LOGDIR="/var/log/$NAME.log"
+ETC=/etc
+LOGDIR=/var/log/$NAME.log
+# FIXME: is this DODTIME variable (and the code around it) really needed?
 DODTIME=2   
 
 test -x $DAEMON || exit 0
 
-set -e
-
-if [ -f /lib/lsb/init-functions ]; then 
+if [ -r /lib/lsb/init-functions ]; then 
 	. /lib/lsb/init-functions
 fi
 
+sourceable() {
+	# Care just about readable, non-backup, files
+	[ -r $1 ] || return 1
+	case $1 in
+		*\~)
+			return 1
+			;;
+	esac
+}
+
 running_pid() {
-    # Check if a given process pid's cmdline matches a given name
-    pid=$1
-    name=$2
-    [ -z "$pid" ] && return 1
-    [ ! -d /proc/$pid ] &&  return 1
-    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
-    # Is this the expected child?
-    [ "$cmd" != "$name" ] &&  return 1
-    return 0
+	# Check if a given process pid's cmdline matches a given name
+	pid=$1
+	name=$2
+	[ "$pid" ] || return 1
+	[ -d /proc/$pid ] ||  return 1
+	read cmd <<-EOF
+		$(cat /proc/$pid/cmdline | tr '\0' '\n')
+	EOF
+	# Is this the expected child?
+	[ "$cmd" = "$name" ] ||  return 1
 }
 
 running() {
-	# Check if the process is running looking at /proc (works for all users)
-  sleep 1
+	# Check if the process is running by looking at /proc
+	# (works for all users).
+	# FIXME: wouldn't it work just as well using 'pidof'?
 	INTERFACE=$1
-	PIDFILE="$INITPIDFILE.$INTERFACE"
-  # No pidfile, probably no daemon present
-	if [ -f "$PIDFILE" ]; then
- 	  pid=`cat "$PIDFILE"`
-	  running_pid $pid $DAEMON || return 1
-    return 0
-  else
-    return 1
-  fi
-  # Obtain the pid and check it against the binary name
-}
-
-force_stop() {
-# Forcefully kill the process
-	for config_file in `find $ETC/$NAME/ -type f -print`
-	do
-		. $config_file
-		PIDFILE="$INITPIDFILE.$INTERFACE"
-    [ ! -f "$PIDFILE" ] && return
-    if running $INTERFACE; then
-        start-start_daemon -K 15 --quiet --pidfile $PIDFILE \
-				--exec $DAEMON -- $DAEMON_OPTS
-        # Is it really dead?
-        [ -n "$DODTIME" ] && sleep "$DODTIME"s
-        if running $INTERFACE; then
-						start-start_daemon -K 9 --quiet --pidfile $PIDFILE \
-						--exec $DAEMON -- $DAEMON_OPTS
-            [ -n "$DODTIME" ] && sleep "$DODTIME"s
-            if running $INTERFACE; then
-                echo "Cannot kill $LABEL (pid=$pid)!"
-                exit 1
-            fi
-        fi
-    fi
-    rm -f $PIDFILE
+	PIDFILE=$INITPIDFILE.$INTERFACE
+	# No pidfile, probably no daemon present
+	_max_repeat=10
+	_repeat=1
+	while [ ! -r $PIDFILE ] && [ $_repeat -le $_max_repeat ]; do
+		echo "waiting for pid file round: $_repeat" >&2
+		sleep 1
+		_repeat=$(($_repeat + 1))
 	done
-  return 0
+	echo "waited ${_repeat}s to find a $INTERFACE pid file" >&2
+	read pid < $PIDFILE || return 1
+	running_pid $pid $DAEMON || return 1
+	# Obtain the pid and check it against the binary name
 }
 
 start_daemon() {
-# Start one daemon for each network interface
-	for config_file in `find $ETC/$NAME/ -type f -print`
-	do
+	# Start one daemon for each network interface
+	# FIXME: Make sure $BASEPIDFILE exists, else daemon start will fail.
+	#	 Creating $BASEPIDFILE is better done in dhcp-probe.postinst.
+	[ -d $BASEPIDFILE ] || mkdir -p $BASEPIDFILE || {
+		echo "Failed to create missing pid file directory $BASEPIDFILE!"
+		return 1
+	}
+	sts=0
+	for config_file in $ETC/$NAME/*; do
+		sourceable $config_file || continue
 		. $config_file
-		PIDFILE="$INITPIDFILE.$INTERFACE"
+		PIDFILE=$INITPIDFILE.$INTERFACE
 		DAEMON_OPTS="-T -p $PIDFILE $INTERFACE"
 		echo -n "Starting $DESC on interface $INTERFACE: "
+
+		# Slow started?  Interface not ready?
+		# Expect an ipv4 ip address set on the interface, within a
+		# reasonable amount of time before kicking off the daemon,
+		# else it will fail.
+		# This loop brings a better success rate.  It will sometimes
+		# still fail to start.  Reason?  Bad karma?
+		max_repeat=10
+		repeat=1
+		while ip=$(sleep 1
+			echo "waiting for an ip on iface $INTERFACE, round: $repeat" >&2
+			while read kw snet dummy; do
+				case $kw in
+					(inet)
+						echo ${snet%/*}
+						sleep 1
+						break
+						;;
+				esac
+			done <<-EOF
+				$(ip addr show dev eth0)
+			EOF
+			) && [ -z "$ip" ] && [ $repeat -le $max_repeat ]; do
+			repeat=$(($repeat + 1))
+		done
+		echo "waited ${repeat}s to get an ip on $INTERFACE" >&2
+
 		start-stop-daemon --start --quiet --pidfile $PIDFILE \
-		--exec $DAEMON -- $DAEMON_OPTS
+			--exec $DAEMON -- $DAEMON_OPTS
 		if running $INTERFACE; then
-			echo " Done."
+			echo "Done."
 		else
-			echo " Failed!"
+			echo "Failed!"
+			sts=1
 		fi
 	done
+	return $sts
 }
 
 stop_daemon() {
 # Stop all existing dhcp_probe daemon
-	for config_file in `find $ETC/$NAME/ -type f -print`
-	do
+	for config_file in $ETC/$NAME/*; do
+		sourceable $config_file || continue
 		. $config_file
-		PIDFILE="$INITPIDFILE.$INTERFACE"
-		if [ -f $PIDFILE ]; then
+		PIDFILE=$INITPIDFILE.$INTERFACE
+		if [ -r $PIDFILE ]; then
 			echo -n "Stopping $DESC on interface $INTERFACE: "
 			start-stop-daemon --stop --quiet --pidfile $PIDFILE 
 			echo "$NAME."
@@ -118,66 +145,90 @@
 	done
 }
 
+force_stop() {
+	# Forcefully kill the process
+	for config_file in $ETC/$NAME/*; do
+		sourceable $config_file || continue
+		. $config_file
+		PIDFILE=$INITPIDFILE.$INTERFACE
+		[ -r "$PIDFILE" ] || return 0
+		if running $INTERFACE; then
+			start-stop-daemon -K 15 --quiet --pidfile $PIDFILE \
+				--exec $DAEMON -- $DAEMON_OPTS
+		        # Is it really dead?
+			[ -z "$DODTIME" ] || sleep "$DODTIME"
+			if running $INTERFACE; then
+				start-stop-daemon -K 9 --quiet --pidfile $PIDFILE \
+					--exec $DAEMON -- $DAEMON_OPTS
+				[ "$DODTIME" ] || sleep "$DODTIME"
+				if running $INTERFACE; then
+					echo "Cannot kill $LABEL (pid=$pid)!"
+					exit 1
+				fi
+			fi
+		fi
+		rm -f $PIDFILE
+	done
+}
 
 
-
-case "$1" in
-  start)
+case $1 in
+	start)
 		start_daemon
-	;;
+		;;
 
-  stop)
+	stop)
 		stop_daemon
-	;;
+		;;
 
-  force-stop)
-		for config_file in `find $ETC/$NAME/ -type f -print`
-		do
+	force-stop)
+		for config_file in $ETC/$NAME/*; do
+			sourceable $config_file || continue
 			. $config_file
-			PIDFILE="$INITPIDFILE.$INTERFACE"
+			PIDFILE=$INITPIDFILE.$INTERFACE
 			echo -n "Forcefully stopping $DESC: "
 			force_stop
 			if ! running $INTERFACE; then
 				echo "$NAME on interface $INTERFACE."
 			else
-				echo " ERROR."
+				echo "ERROR."
 			fi
 		done
-	;;
+		;;
 
 	force-reload)	# Need to be improved
-    echo "Reload operation is not supported -- use restart."
+		echo "Reload operation is not supported -- use restart."
 		exit 1
-	;;
+		;;
 
-  restart)
-    echo -n "Restarting $DESC: "
+	restart)
+		echo -n "Restarting $DESC: "
 		stop_daemon
-		[ -n "$DODTIME" ] && sleep $DODTIME
+		[ -z "$DODTIME" ] || sleep $DODTIME
 		start_daemon
 		echo "$NAME."
-	;;
+		;;
 
-  status)
-		for config_file in `find $ETC/$NAME/ -type f -print`
-		do
+	status)
+		for config_file in $ETC/$NAME/*; do
+			sourceable $config_file || continue
 			. $config_file
-			PIDFILE="$INITPIDFILE.$INTERFACE"
+			PIDFILE=$INITPIDFILE.$INTERFACE
 			echo -n "$LABEL is "
 			if running $INTERFACE;  then
-					echo "running on interface $INTERFACE"
+				echo "running on interface $INTERFACE"
 			else
-					echo " not running."
-					exit 1
+				echo "not running."
+				exit 1
 			fi
 		done
-    ;;
+		;;
 
-  *)
-	N=/etc/init.d/$NAME
-	echo "Usage: $N {start|stop|restart|status|force-stop}" >&2
-	exit 1
-	;;
+	*)
+		N=/etc/init.d/$NAME
+		echo "Usage: $N {start|stop|restart|status|force-stop}" >&2
+		exit 1
+		;;
 esac
 
 exit 0
+ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+ DAEMON=/usr/sbin/dhcp_probe
+ LABEL=dhcp_probe
+ NAME=dhcp-probe
+ PIDFILE=dhcp_probe.pid
+ BASE_RUNNING=/var/run
+ BASEPIDFILE=/var/run/dhcp-probe
+ INITPIDFILE=/var/run/dhcp-probe/dhcp_probe.pid
+ DESC=dhcp-probe daemon
+ ETC=/etc
+ LOGDIR=/var/log/dhcp-probe.log
+ DODTIME=2
+ test -x /usr/sbin/dhcp_probe
+ [ -r /lib/lsb/init-functions ]
+ . /lib/lsb/init-functions
+ FANCYTTY=
+ [ -e /etc/lsb-base-logging.sh ]
+ true
+ start_daemon
+ [ -d /var/run/dhcp-probe ]
+ sts=0
+ sourceable /etc/dhcp-probe/dhcp-probe.eth0
+ [ -r /etc/dhcp-probe/dhcp-probe.eth0 ]
+ . /etc/dhcp-probe/dhcp-probe.eth0
+ INTERFACE=eth0
+ MAC=90:e6:ba:13:9e:29
+ IPV4=192.168.98.121
+ IPV4_MASK=192.168.98.255
+ PIDFILE=/var/run/dhcp-probe/dhcp_probe.pid.eth0
+ DAEMON_OPTS=-T -p /var/run/dhcp-probe/dhcp_probe.pid.eth0 eth0
+ echo -n Starting dhcp-probe daemon on interface eth0: 
+ max_repeat=10
+ repeat=1
+ sleep 1
+ echo waiting for an ip on iface eth0, round: 1
waiting for an ip on iface eth0, round: 1
+ ip addr show dev eth0
+ read kw snet dummy
+ read kw snet dummy
+ read kw snet dummy
+ echo 192.168.98.121
+ sleep 1
+ break
+ ip=192.168.98.121
+ [ -z 192.168.98.121 ]
+ echo waited 1s to get an ip on eth0
waited 1s to get an ip on eth0
+ start-stop-daemon --start --quiet --pidfile 
/var/run/dhcp-probe/dhcp_probe.pid.eth0 --exec /usr/sbin/dhcp_probe -- -T -p 
/var/run/dhcp-probe/dhcp_probe.pid.eth0 eth0
+ running eth0
+ INTERFACE=eth0
+ PIDFILE=/var/run/dhcp-probe/dhcp_probe.pid.eth0
+ _max_repeat=10
+ _repeat=1
+ [ ! -r /var/run/dhcp-probe/dhcp_probe.pid.eth0 ]
+ [ 1 -le 10 ]
+ echo waiting for pid file round: 1
waiting for pid file round: 1
+ sleep 1
+ _repeat=2
+ [ ! -r /var/run/dhcp-probe/dhcp_probe.pid.eth0 ]
+ echo waited 2s to find a eth0 pid file
waited 2s to find a eth0 pid file
+ read pid
+ running_pid 1725 /usr/sbin/dhcp_probe
+ pid=1725
+ name=/usr/sbin/dhcp_probe
+ [ 1725 ]
+ [ -d /proc/1725 ]
+ tr \0 \n
+ cat /proc/1725/cmdline
+ read cmd
+ [ /usr/sbin/dhcp_probe = /usr/sbin/dhcp_probe ]
+ echo Done.
+ return 0
+ exit 0

Reply via email to