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