Surprise - AttributeError: 'bytes' object has no attribute 'find'



  • Greetings all.

    This one seems odd. I have code that publishes NMEA messages over mqtt, on a Lopy4 (fw 1.17.3.b1) . This code has been working fine for ages. I've recently discovered mqtt-spy and had left my Lopy4s running so that I could look at graphs of allocated memory. It was obvious that the Lopy4 on the pytrack had rebooted for some reason and I found this in the scrollback buffer:

    Traceback (most recent call last):
      File "main.py", line 118, in run
      File "main.py", line 114, in run
      File "main.py", line 114, in run
      File "navigator.py", line 97, in do_gps_work
      File "navigator.py", line 86, in gps_work
      File "navigator.py", line 58, in gps_proccess_data
    AttributeError: 'bytes' object has no attribute 'find'
    Traceback (most recent call last):
      File "node.py", line 190, in client_work
      File "/flash/lib/mqtt.py", line 156, in wait_msg
    OSError: [Errno 9] EBADF
    FATAL:; Watchdog will reboot soon!
    Done
    MicroPython v1.8.6-849-83e2f7f on 2018-03-19; LoPy4 with ESP32
    Type "help()" for more information.
    >>>
    

    I was horrified, and immediately fixed my spelling in the code. Then I wondered what had gone wrong.

    The first exception, caught in the main thread shows that the error occurred in this code. I've commented on the line in question.

    def gps_process_data(self, loops, ival):
        if(loops % ival) == 0:
            lines = self.data.split(b'\r\n')
            self.data  = b''
            for line in lines:
                stx_idx = line.find(self.stx) # this is line 58
                if stx_idx >= 0:
                    tag_idx = line[stx_idx:].find(self.tag)
                    if tag_idx >= 0 and (len(line)-tag_idx) >= 3:
                        nmea_line = line[stx_idx:].rstrip(b'\r')
                        nmea_msg = nmea_line[0:6]
                        if nmea_msg in self.wanted_nmea:
                            topic = self.node.client_id+'/gpspub/nmea/'+str(nmea_msg,"utf-8")
                            self.node.client_try_publish(topic, nmea_line, False, 0)
                    else:
                        self.data += line[stx_idx:]
        else:
            self.data  = b''
    

    As this code has run gazillions of times before and is happily running now, I can't quite grasp how the bytes object suddenly has no find() method. I can only assume that something somewhere has gone very wrong.
    Perhaps the 2nd exception, the OSError/EBADF in MQTTClient.wait_msg() is another symptom of the same general badness. This isn't the first time I've seen that, but I normally see that after an (I think this was it) an OSError ECONNRESET (or similar) has occurred in another thread during an mqtt send, and the EBADF is the listening thread barfing after the connection has been closed, but there is no evidence of that here.

    In general, my codebase hasn't changed much in 6 months.
    Is anyone else experiencing interrmittent random badness like this?



  • Replying to myself here, I now see that the OSError/EBADF in MQTTClient.wait_msg() is occurring as the stack unwinds in the main thread, which takes out the MQTTClient instance. It is the exception handler in the main thread that enables the watchdog, delays and prints the FATAL message.
    So the cause of the original exception still remains unknown.


Log in to reply
 

Pycom on Twitter