HomePage RecentChanges

GPSD bug

I discovered a possible bug in gpsd.

What happens

I noticed that certain commands sent to gpsd seemed to stop working after a few minutes, and there are problems with the timestamp of gpsd output.

This happens on my dual-core laptop with a qstarz BT-Q810 bluetooth gps. A different bluetooth gps is fine.

The problem

GPSD has a problem receiving more than 1 NMEA sentence at a time. It expects to receive either a full sentence or a fragment.

It fails to try to parse the incoming buffer multiple times. This causes an internal buffer to grow to a large size. Is is usually only used to store fragments of NMEA sentences.

gpsd keeps working, but some weired things happen.

Verified in a svn pull on 13 September 2007.

Verify if you have the problem

Run gpsd on the command line with maximum debug. After a few minutes you will see the buffer max out.

gpsd: Packet discard of 68, chars remaining is 934

Reproduction

The problem can be reproduced by editing gpsfake to send 2 NMEA sentences to gpsd at a time.

Modify the feed function in gpsfake.py to be as follows

def feed(self):
        "Feed a line from the contents of the GPS log to the daemon."
        line = self.testload.sentences[self.index % len(self.testload.sentences)]
        self.index += 1
        line = line + self.testload.sentences[self.index % len(self.testload.sentences)]
        os.write(self.master_fd, line)
        # Delay so we won't spam the buffers in the pty layer or gpsd itself.
        # Assumptions: 1 character is 10 bits (generous; at 8N1 it will be 9).
        time.sleep((10.0 * len(line)) / self.speed)
        self.index += 1

And modify gpsfake.py to launch the local copy of gpsd

"Spawn a daemon instance."
        self.spawncmd = "./gpsd -N -S %s -F %s -P %s %s" % (port,self.control_socket, self.pidfile, options)

Or, you can just apply the following patch to gpsfake.py which contains the above two changes.

283a284
> 
286a288,289
>         self.index += 1
>         line = line + self.testload.sentences[self.index % len(self.testload.sentences)]
309c312
<         self.spawncmd = "gpsd -N -S %s -F %s -P %s %s" % (port, self.control_socket, self.pidfile, options)
---
>         self.spawncmd = "./gpsd -N -S %s -F %s -P %s %s" % (port,self.control_socket, self.pidfile, options)

Once you have that set up, launch gpsfake as follows. You will need some captured NMEA sentences in the "replay" file. Any should do.

./gpsfake -c 4 -l -D 99999 replay

You should see debug statement like "gpsd: Packet discard of 75, chars remaining is 265".

After a few minutes the buffer should keep rising, until it maxes out around 1000 e.g. "gpsd: Packet discard of 68, chars remaining is 934"

Log

The full log output from running gpsfake is here GPSD bug log.