Debugging why pps line discipline gets removed after 5 seconds

I got my udev rules all set up to use an NMEA GPS board which provides PPS with ntpd:

SUBSYSTEM=="pps", MODE="0664" GROUP="dialout"
KERNEL=="ttyS0" SYMLINK+="gps0"
KERNEL=="ttyS0", RUN+="/bin/setserial /dev/%k low_latency"
KERNEL=="ttyS0", RUN+="/usr/sbin/ldattach pps /dev/%k"
KERNEL=="pps0" SYMLINK+="gpspps0"

And it almost seems to work great:

$ sudo udevadm trigger -y ttyS0 ; ls -l /dev/gps*
lrwxrwxrwx 1 root root 5 Mar 19 09:43 /dev/gps0 -> ttyS0

What? Where’s the pps device? dmesg (or journalctl) reveals:

[ 4083.237473] pps pps0: new PPS source serial0
[ 4083.237479] pps pps0: source "/dev/ttyS0" added
[ 4086.238700] pps pps0: removed

If I immediately “systemctl start ntp” after triggering udev, it seems to keep it, and ntpd gets to use pps as expected. But that’s not going to work reliably on boot. So, something’s causing it to be removed. After a bit of frusturation, I decided to poke around a bit with the excellent perf-tools

I did a lot of poking around with execsnoop and functrace, but then when I was getting inconsistent behavior, I got to looking at what had /dev/ttyS0 open. A lot of things did. Several ldattach processes! Aha. So, I reread the ldattach man page and am reminded that it resets the line discipline when killed. Presumably udev just doesn’t allow these commands to stay running in the background. So, it seems like running it as a service from systemd is the way to go, e.g: LinuxPPS wiki In my case, I did:

[Unit]
Description=Line Discipline for GPS Timekeeping for %i
Before=ntp.service

[Service]
ExecStart=/usr/sbin/ldattach pps /dev/%i
Type=forking

[Install]
WantedBy=multi-user.target

And I commented out the line with ldattach in the udev rule.

Leave a Reply

Your email address will not be published. Required fields are marked *