Skip to content

Instantly share code, notes, and snippets.

@dsd
Last active May 25, 2016 20:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dsd/9f83c4830ab78ce94078aedb2cf16a8f to your computer and use it in GitHub Desktop.
Save dsd/9f83c4830ab78ce94078aedb2cf16a8f to your computer and use it in GitHub Desktop.
usb-modeswitch: run dispatcher through init system
From: Daniel Drake <drake@endlessm.com>
Careful rework of usb_modeswitch_dispatcher udev activation to solve
these problems:
1. Current code passes stdout/stderr descriptors all the way from udev's
worker to the usb_modeswitch_dispatcher process. udev monitors those
descriptors, and since they remain active, udev is blocked until
usb_modeswitch_dispatcher exits.
So, usb_modeswitch_dispatcher does the modeswitch and then
waits a while to see if udev udev auto-loads any modem drivers at that
point. But udev is blocked because usb_modeswitch_dispatcher is still
running. This results in usb_modeswitch_dispatcher deciding that no
driver was auto-loaded, and force-loading the wrong driver in some
circumstances.
2. The obvious fix of closing those file descriptors reveals the 2nd problem,
that udev will kill all the child processes that were launched by
/lib/udev/usb_modeswitch once that exits, and this is now clearly
documented in the udev man page.
A change of approach is needed here and I think the best option is to use
the init system to launch the dispatcher, with the following considerations:
1. The versions of Fedora and Ubuntu that I have in front of me (F23, U16.04)
don't install the systemd unit file. They will have to start doing so now.
And they will install it in /lib, so the current systemd check has to be
reworked. Hopefully this new approach is reasonable but it could be tricky.
http://unix.stackexchange.com/questions/18209/detect-init-system-using-the-shell
2. Don't fork a background subshell, don't attempt to background anything.
We need to ensure that the init system has been successfully instructed
to start the modeswitch service before this script exits. If we exit while
that is ongoing in the background, those background processes will likely
be killed before they complete.
http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?f=2&t=2329
--- usb-modeswitch-2.3.0/usb_modeswitch.sh.orig 2016-01-11 13:18:57.000000000 -0600
+++ usb-modeswitch-2.3.0/usb_modeswitch.sh 2016-05-25 13:07:05.106359971 -0600
@@ -73,26 +73,27 @@ case "$1" in
exit 0
;;
esac
-(
+
IFS='/' read -r p1 p2 <<EOF
$1
EOF
PATH=/bin:/sbin:/usr/bin:/usr/sbin
count=20
+
+init_path=`readlink /sbin/init`
+
while [ $count != 0 ]; do
if [ ! -e "/usr/sbin/usb_modeswitch_dispatcher" ]; then
sleep 1
count=$(($count - 1))
else
- if [ -e "/etc/systemd/system/usb_modeswitch@.service" ]; then
- exec systemctl --no-block start usb_modeswitch@$p1'_'$p2.service
+ if [ `basename $init_path` = "systemd" ]; then
+ systemctl --no-block start usb_modeswitch@$p1'_'$p2.service
elif [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then
- exec initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1
- else
- exec usb_modeswitch_dispatcher --switch-mode $1 &
+ initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1
fi
- exit 0
+ break
fi
done
-) &
+
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment