-   Slackware (
-   -   [solved] udev rule not starting gpsd during boot (

xj25vm 05-29-2011 05:25 AM

[solved] udev rule not starting gpsd during boot
I'm trying to configure gpsd 2.96 to start automatically from udev rule on a Slack 13.37 box.

1. I've compiled and installed gpsd from sources and made sure it starts manually.
2. I've copied the /lib/udev/gpsd.hotplug and /lib/udev/gpsd.hotplug.wrapper scripts in their places from the source tree and made them executable.
3. I've copied the gpsd.rules file from sources into /etc/udev/rules.d
4. I renamed it 99-persistent-gpsd.rules to run late in the bootup process.
5. I've copied the /etc/default/gpsd file from sources and made sure it has the right settings inside.

Now, for the results. If I plug the gps usb dongle in while the system runs, it starts gpsd if it is not started, and it connects to it just as it should. But if I start the system with the dongle in, gpsd doesn't get started during boot. I can't find any relevant message in /var/log/syslog or /var/log/messages for boot time. There is stuff there from when I plug the dongle in while the system is running though. It's like udev ignores the rules for it at boot time.

Is there something in the Slackware boot scripts that would prevent running those scripts (/lib/udev/gpsd.hotplug.wrapper which in turn runs /lib/udev/gpsd.hotplug which is a Python script)?

Here is the contents of 99-persistent-gpsd.rules (ignore the comments referring to Debian, it was meant for a Debian box). My usb gps adapter is the first one - the Prolific chipset one:


# udev rules for gpsd
# $Id: gpsd.rules 5861 2009-08-03 13:41:01Z bzed $
# GPSes don't have their own USB device class.  They're serial-over-USB
# devices, so what you see is actually the ID of the serial-over-USB chip.
# Fortunately, just two of these account for over 80% of consumer-grade
# GPS sensors.  The gpsd.hotplug.wrapper script will tell a running gpsd
# that it should look at the device that just went active, because it
# might be a GPS.
# The following setup works on Debian - something similar will apply on
# other distributions:
#  /etc/udev/gpsd.rules
#  /etc/udev/rules.d/025_gpsd.rules -> ../gpsd.rules
#  /lib/udev/gpsd.hotplug.wrapper
#  /lib/udev/gpsd.hotplug
# Setting the link in /etc/udev/rules.d activates the rule and determines
# when to run it on boot (similar to init.d processing).

SUBSYSTEM!="tty", GOTO="gpsd_rules_end"

# Prolific Technology, Inc. PL2303 Serial Port
SYSFS{idVendor}=="067b", SYSFS{idProduct}=="2303", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# ATEN International Co., Ltd UC-232A Serial Port [pl2303]
SYSFS{idVendor}=="0557", SYSFS{idProduct}=="2008", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# FTDI 8U232AM
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="6001", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# Cypress M8/CY7C64013 (DeLorme uses these)
SYSFS{idVendor}=="1163", SYSFS{idProduct}=="0100", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# PS-360 OEM (Microsoft GPS sold with Street and Trips 2005)
SYSFS{idVendor}=="067b", SYSFS{idProduct}=="aaa0", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# Garmin International GPSmap, various models (tested with Garmin GPS 18 USB)
SYSFS{idVendor}=="091e", SYSFS{idProduct}=="0003", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# Cygnal Integrated Products, Inc. CP210x Composite Device (Used by Holux m241)
SYSFS{idVendor}=="10c4", SYSFS{idProduct}=="ea60", SYMLINK+="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"
# u-blox AG, u-blox 5 (tested with Navilock NL-402U)
SYSFS{idVendor}=="1546", SYSFS{idProduct}=="01a5", SYMLINK="gps%n", RUN+="/lib/udev/gpsd.hotplug.wrapper"

ACTION=="remove", RUN+="/lib/udev/gpsd.hotplug.wrapper"


Thank you

Didier Spaier 05-29-2011 05:57 AM

There is a slackbuild available for gpsd on, see

Not sure it will answer you question -- but at least it can help you keep your system clean ;)

xj25vm 05-29-2011 06:40 AM

Thanks for the reply. I've actually used the slackBuilds script - just modified it to use version 2.96 instead of 2.95. The slackBuilds script does not install or configure any of the udev rules. I had to copy them manually from the source code. If I manage to get it going, I would like to go back to slackBuilds and suggest they modify their script to automatically configure the udev stuff.

As a follow-up to my post above - I know that the rule gets triggered during boot - because gps0 shows up in /dev - otherwise it would be just ttyUSB0. I just can't figure out why the RUN script doesn't get run.


55020 05-29-2011 06:56 AM

I'm pretty sure the SBo gpsd won't help with the udev problem -- it doesn't even try to do anything with udev rules. So thanks to xj25vm for poking it with a stick :)

I'll do some experiments this afternoon, and if we end up with success, I'll try to include some optional support for udev in the SBo SlackBuild -- even if it's just a new paragraph in the README. (Niels Horn just approved an update for version 2.96, so apologies to Niels if we change it again in the near future!)

xj25vm 05-29-2011 08:03 AM

It seems there is a problem with the udev setup - either in general, or the way it is configured in Slackware. I can't run anything from a udev rule. I've tried the following simple setup which is supposed to write a simple file in /var/run during boot if the gps dongle is connected:


ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", RUN="/lib/udev/gpsd.test"



/bin/touch /var/run/gpsd.test

The above produces nothing. I've tried turning up logging on udev - to see what's happening - but can't find anything relevant in the logs. It's like there is no way of running any sort of script from udev during boot. Unless I'm missing an essential bit of information somewhere. I know the attributes in the udev rule are correct, because if I use SYMLINK instead of RUN - I do end up with the correct symlink under /dev created during boot.

I don't think we stand a chance of getting the gpsd started automatically by udev during boot if the RUN argument doesn't work (although, bizarrely, it works fine if the computer is booted/running and the usb gps dongle is inserted).


55020 05-29-2011 10:56 AM

Well, I think I know what's going on here, and it isn't pretty.

gpsd insists on having a control socket at /var/run/gpsd.sock (even if you set the relevant variable in /etc/default/gpsd to a null string). Unfortunately, neither gpsd nor /lib/udev/gpsd.hotplug can create this socket when /etc/rc.d/rc.udev is doing its coldplug thing, because the root filesystem is still read-only at this point in the boot.

(Digression: you can see this happening if you dial up udev's log level and ctrl-s the display at just the right point.


udevd-work[1057]: '/etc/udev/gpsd-hotplug-wrapper' started
udevd-work[1057]: '/etc/udev/gpsd-hotplug-wrapper' (stderr) 'gpsd:ERROR: can't listen on local socket /var/run/gpsd.sock'
udevd-work[1057]: '/etc/udev/gpsd-hotplug-wrapper' (stderr) 'gpsd:ERROR: control socket create failed. netlib error -1'
udevd-work[1057]: '/etc/udev/gpsd-hotplug-wrapper' returned with exitcode 0

Digression continues: because the filesystem is still read-only, udevd's output isn't logged into /var/log/messages -- I had to write the above messages down with a biro and type them by hand -- and also presumably that's why your attempt to touch /var/run/gpsd.test fails.)

Note also, that despite the above failure, the other part of the udev rule -- creating the extra device symlink /dev/gpsN -- actually works ok.

Maybe there would be a happy ending if only gpsd.hotplug and gpsd.hotplug.wrapper exited with an error code having failed to create the socket. Then, when Slackware later invokes udevadm trigger --type=failed, the scripts would run again, and would succeed. (This stuff is complicated. Am I getting it right?!) Alas, this does not happen. The reason why it doesn't or can't return an error code might be the unrelated situation that's described in the comments in gpsd.hotplug


# In recent versions of udev, the gpsd script runs in series with
# the task that creates the real /dev/ttyUSB0 device
# node. Unfortunately, the gpsd script runs BEFORE the creation of
# the node, and the node is not created until after you kill the
# gpsd script, because the gpsd script waits forever for the node
# to appear.
# This is a race condition, and is best fixed by running the
# actual wait/hotplug portion in the background.
All things considered, the special moment has now arrived where I point out that, just because I package this stuff for SBo doesn't mean that I endorse the way upstream does things :rolleyes:

The best fix for booting would be to edit rc.local so that it starts gpsd if /dev/gps0 exists. You can leave everything else exactly the way it is now so that hotplug will also work.

catkin 05-29-2011 11:20 AM

Here's a scrippet that might help.

while true
    buf=$( runlevel )
    runlevel=${buf#* }
    case $runlevel in
        0 | 1 | s | S )
            sleep 5
<start gpsd>

Alternatively you could loop waiting for the necessary file system(s) to be writable.

xj25vm 05-29-2011 12:00 PM

Hi 55020,

I think I followed pretty much all your explanation. Thank you for that - I didn't realise the first pass of udev is done while the root filesystem is in read-only mode. I am on the gpsd mailing list - and I will try to see if there is any interest in modifying the two hotplug scripts to return a non-zero value in case of failure.

The problem with starting gpsd from rc.local (which I have considered) is that once the boot is out of the way, I will end up with a running gpsd, but not with a usb gps adapter connected to it - if it was plugged in before the computer is started. That is because the hotplug script sends commands to the gpsd daemon through the socket to connect to the gps device. That unless I start gpsd with the device name (/dev/ttyUSB0) on the command line. This relies on the gps dongle being assigned the same device name everytime - which might just work in my particular setup. It's just not that elegant as the hotplug.

xj25vm 05-29-2011 12:39 PM

I'm trying to modify the gpsd.hotplug.wrapper script to return a failure message if it can't write to the filesystem - so that it get's re-run after the filesystem is mounted rw.

I'm experimenting with a very simple script like this:



if ! /bin/touch /var/run/gpsd.test; then

  sleep 5
  exit 1


sleep 5
exit 0

My rule file is this:


ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", RUN="/lib/udev/gpsd.test"

I can see it is run during the boot (as it pauses the boot for 5 seconds, that's why I used the sleep statements). However, it doesn't seem to run on the second udev trigger (retry=failed) later on. The system doesn't pause, and the file doesn't get created.

What does it take to register a rule as failed with udev - so that it gets re-run later on? I was thinking an exit code of 1 for a bash script should have been enough. I've read the man page for udev and udevadm - but they don't seem to say how exactly to fail a rule.


P.S. - Sorry for being a bit OT here - but I thought I better keep all the conversation belonging to the gpsd and udev problem in one place.

55020 05-29-2011 01:17 PM


Originally Posted by xj25vm (Post 4370258)
The problem with starting gpsd from rc.local (which I have considered) is that once the boot is out of the way, I will end up with a running gpsd, but not with a usb gps adapter connected to it - if it was plugged in before the computer is started. That because the hotplug script sends commands to the gpsd daemon through the socket to connect to the gps device. That unless I start gpsd with the device name (/dev/ttyUSB0) on the command line. This relies on the gps dongle being assigned the same device name everytime - which might just work in my particular setup. It's just not that elegant as the hotplug.

You could use /dev/gps0 instead of /dev/ttyUSB0 on the gpsd command line. At least that'll point to whatever udev considers to be the first GPS device. But yeah, it won't work for anything other than simple use cases.

The udev rules supplied by gpsd are neither elegant nor foolproof; they assume that more or less any serial USB converter is a GPS. I use the exact same serial cable with an eTrex and at other times with various scientific data loggers, and additionally I've got a diabetes blood glucose meter with the exact same PL2303 USB id. There is no way that udev can distinguish these use cases. And that's why I don't use gpsd hotplug. It doesn't fit my lifestyle :cool: but YMMV...

xj25vm 05-29-2011 04:20 PM

I have used gpsd with manual start for almost two years now on my own laptop - and I would have kept on using it. But I'm currently working on a vehicle onboard tracking system, using Slack and gpsd - and that's when I stumbled over this whole $%^$ - erm, extra complication. This computer will be physically locked in its case, will start automatically when the engine starts - so it needs a reliable way of starting gpsd without any intervention. I will probably stick with doing "gpsd -n /dev/ttyUSB0" from rc.local - and this will fit my use case this time.

I would have loved it, however, if I could have come up with a more flexible script to do things properly, from udev - which would have worked well on Slackware - so that it can be added to the SBo repository. Well, I suppose you win some, you lose some :-) .

In retrospect, gpsd should really include the option to scan for usb devices itself when it starts and add the right ones automatically to it's pool. This way a gpsd startup script just doing "gpsd --watch-usb" or something similar would have been enough. At worst, a udev rule including "gpsd --rescan" to tell gpsd when to have another look for new devices should cover all situations. At least I think that would have been the neatest way.

55020 05-29-2011 06:16 PM

How about leaving 99-persistent-gpsd.rules in place, and putting this in /etc/rc.local

if [ -l /dev/gps0 -a -x /lib/udev/gpsd-hotplug ]; then
  /lib/udev/gpsd-hotplug add $(readlink /dev/gps0)

I think it does everything which upstream's code purports to do, except that it won't start gpsd in single-user mode coldplug. And IMO that's most definitely a feature, not a bug. Oh, and it doesn't cope with multiple devices (just repeat for each /dev/gps*).

Meanwhile, to answer your earlier question: "What does it take to register a rule as failed with udev - so that it gets re-run later on?" -- apparently this is the magic invocation (but I had to look it up, and haven't tried it).


ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", RUN{fail_event_on_error}="/lib/udev/gpsd.test"

xj25vm 05-29-2011 06:37 PM

Thank you for that. In that case, I wonder if we can suggest two modifications to the gpsd team:

1. Modify their existing udev rule file to add "{fail_event_on_error}" for every line of the file.
2. Modify the gpsd.hotplug.wrapper script to include a test along the lines:


# test if /var/run is on a fs mounted rw
if /bin/touch /var/run/gpsd.test; then
  rm /var/run/gpsd.test
  exit 1

Unless somebody can think of a neater way to test if the file-system is mounted rw.

This way, the gpsd.hotplug.wrapper should fail on the first udev run, and should succeed on the second run.

Wouldn't the two modifications above make the upstream setup fully compatible with Slackware (in theory - I haven't tried it yet)? - while keeping it compatible with the other distros as well. I really would like if that would be the case, instead of having some modifications which only apply to one distribution. It would also be easier to package.

xj25vm 05-30-2011 03:58 AM

I've just tried the {fail_event_on_error} option and it seems to do nothing. It runs the script on the first pass of udev (and fails to write the file to /var/run), but doesn't run it on the second pass.

xj25vm 05-30-2011 04:14 AM

1 Attachment(s)
OK - I think I have a compromise solution to suggest for the SBo repository. I've built an rc.gpsd script to go in /etc/rc.d and be triggered from rc.local. This will:

1. Start gpsd
2. Pass ttyUSB0 (or any other device) on the command line, in case the usb dongle was already plugged in when the computer booted.
3. Also pass -F /var/run/gpsd.sock option on the command line, so that the gpsd daemon can be interracted with by gpsctl through udev, and receive any new device plugged in after the computer boots.

In conjunction with using /udev/lib/gpsd.hotplug, /udev/lib/gpsd.hotplug.wrapper, gpsd.rules (maybe renamed /etc/udev/rules.d/99-persistent-gpsd.rules to fit what seems to be Slackware naming style) - this should cover most use cases, of having the device plugged in when the computer starts, and plugging it in later.

I attach the rc.gpsd here (remove .txt from the end). The other files are in the gpsd sources.

What do you think?

All times are GMT -5. The time now is 08:39 AM.