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", RUN+="/bin/setserial /dev/%k low_latency"
KERNEL=="ttyS0", RUN+="/usr/sbin/ldattach pps /dev/%k"
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:
Description=Line Discipline for GPS Timekeeping for %i
ExecStart=/usr/sbin/ldattach pps /dev/%i
And I commented out the line with ldattach in the udev rule.