GPSD opstart, del 3: Så virker det!

I føljetonen på opstart af gpsd servicen, så har jeg endelig løst problemet.

Race conditions / concurrency problemer er notorisk svære at løse, og det var også tilfældet for den her. Jeg brugte det meste af i går på grave ind på problemet fra rigtig mange sider, og det vil være føre vidt at komme ind på alle de ting jeg har prøvet.

Løsningen, som ikke er en rigtig løsning, men i stedet det man i software udvikler kredse kalder for et “ugly hack” eller en “workaround”, der kun er en midlertidig løsning.

  • Løsningen er at fjerne al tilsluttet GPS hardware og så køre:

    sudo killall gpsd
    sudo dpkg-reconfigure gpsd
    
  • … hvor man:

    • Svarer ja, til Skal gpsd starte automatisk?
    • Svarer ja, til Skal gpsd håndtere tilsluttede USB GPS-modtagere automatisk?
    • Lader tekst feltet være tomt for Enhed GPS-modtageren er tilsluttet:
    • i tekstfeltet for Tilvalg for gpsd: skriver:

      /dev/serial/by-id/usb-Silicon_Labs_CP2104_USB_to_UART_Bridge_Controller_00784403-if00-port0
      
  • For tekstfeltet Sti for gpsd kontrolsokkel: vælges der Ok for den forudfyldte tekst som skal være:

    /var/run/gpsd.sock
    
  • Resultat kan ses i /etc/default/gpsd, som i dette tilfælde så bliver:

    # Default settings for gpsd.
    # Please do not edit this file directly – use `dpkg-reconfigure gpsd’ to
    # change the options.
    START_DAEMON=”true”
    GPSD_OPTIONS=”/dev/serial/by-id/usb-Silicon_Labs_CP2104_USB_to_UART_Bridge_Controller_00784403-if00-port0″
    DEVICES=””
    USBAUTO=”true”
    GPSD_SOCKET=”/var/run/gpsd.sock”
    
  • Filen /lib/udev/rules.d/60-gpsd.rules modificeres til at have det følgende indhold, sådan at udev reglen kun aktiveres for lige nøjagtig den serielle port, der er den indkøbte USB GPS enhed:

    # udev rules for gpsd
    # This file is Copyright (c) 2010 by the GPSD project
    # BSD terms apply: see the file COPYING in the distribution root for details.
    #
    # 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 and Ubuntu – something similar
    # will apply on other distributions:
    #
    # /lib/udev/rules.d/25-gpsd.rules
    # /lib/udev/gpsd.hotplug
    #
    # Setting the link in /lib/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”
    # Cygnal Integrated Products, Inc. CP210x Composite Device (Used by Holux m241 and Wintec grays2 wbt-201) [linux module: cp210x]
    ATTRS{idVendor}==”10c4″, ATTRS{idProduct}==”ea60″, SYMLINK+=”gps%n”, RUN+=”/lib/udev/gpsd.hotplug”
    ACTION==”remove”, RUN+=”/lib/udev/gpsd.hotplug”
    LABEL=”gpsd_rules_end”
    
  • Til sidst opdaterer man så udev reglerne med:

    sudo udevadm control –reload
    
  • … og tilslutter så USB GPS devices og genstarter Raspberry Pi med:

    sudo shutdown -r now
    

Hvis man brugte /dev/ttyUSB0 virker det altid ved boot, og den er også Plug´n Play – man kan tage USB GPS hardwaren af, og sætte den til Raspberry Pi.

Problemet med brug af /dev/ttyUSB0 er at det device navn er samspilsramt med andre serielle porte, da en anden seriel port kunne være den første, der får /dev/ttyUSB0, som altså er en ny race condition.

Hvis jeg bruger det device jeg har i /etc/defaults/gpsd:

/dev/serial/by-id/usb-Silicon_Labs_CP2104_USB_to_UART_Bridge_Controller_00784403-if00-port0

… så vil det ikke virke, hvis gps hardwaren ikke er tilsluttet ved boot. Det virker heller ikke, hvis man senere tilslutter GPS devicet – gpsd er stadig lige tavs.

Så USB GPS hardwaren skal altså foreløbig altid være tilsluttet før start.

Jeg mener at jeg kan pinne en seriel port til f.eks. /dev/ttyUSB1, og hvis det er rigtigt, så ændres GPS_OPTION i /etc/default/gpsd til at være /dev/ttyUSB0.

Problemet er dermed løst – sådan da.

En mere endelig løsning står på TODO listen. Herunder at jeg laver mine egne programmer der erstatter /usr/sbin/gpsdctl og / eller /lib/udev/gpsd.hotplug, der kan undgå den nævnte gpsd opstarts-race condition.