adafruit / Adafruit_CircuitPython_AzureIoT

Access to Microsoft Azure IoT device, messaging, and job services from CircuitPython!
MIT License
20 stars 15 forks source link

Fix 24 CPython sockets compatibility #27

Closed askpatrickw closed 3 years ago

askpatrickw commented 3 years ago

fixes #24

When its completed... draft PR to track. Suggestions welcome ;-)

ladyada commented 3 years ago

some folks are out next week, let us know when its ready to review!

askpatrickw commented 3 years ago

@brentru Here's where I'm at with the IoT Central path...

The AzureIOT.DeviceRegistration works (gives you your IoT Hub server name and uses Requests) but when the SSL connection to the IoT Hub starts, MiniMQTT keeps failing with MemoryErrors and eventually fails completely.

The MiniMQTT code is here https://github.com/adafruit/Adafruit_CircuitPython_MiniMQTT/blob/master/adafruit_minimqtt/adafruit_minimqtt.py#L245 That logic is the same logic as in Requests.

Traceback (most recent call last):
  File "code.py", line 88, in <module>
  File "/lib/adafruit_azureiot/iotcentral_device.py", line 162, in connect
  File "/lib/adafruit_azureiot/iot_mqtt.py", line 397, in connect
  File "/lib/adafruit_azureiot/iot_mqtt.py", line 142, in _create_mqtt_client
  File "/lib/adafruit_minimqtt/adafruit_minimqtt.py", line 443, in connect
  File "/lib/adafruit_minimqtt/adafruit_minimqtt.py", line 277, in _get_connect_socket
RuntimeError: Repeated socket failures

I'm really stumped by why the exception is MemoryError. Any suggestions on how to proceed or where to look next?

askpatrickw commented 3 years ago

@tannewt since Brent is off this week and this logic is very similar to requests, do you have any suggestions on next steps to look into these MemoryErrors? I've tried this on a FeatherS2 and a MetroS2 just to be sure and get the same issue.

tannewt commented 3 years ago

It's not clear to me what the backtrace is for a memory error because the one you posted is RuntimeError. Where is the memory error being raised?

askpatrickw commented 3 years ago

It's not clear to me what the backtrace is for a memory error because the one you posted is RuntimeError. Where is the memory error being raised?

Sorry, I wasn't clear, through print debugging, I determined the reason we get the RuntimeError is in this try we hit MemoryError repeatedly until we exhaust the retry_count

retry_count = 0
while retry_count < 5 and sock is None:
      retry_count += 1

      try:
          sock = self._socket_pool.socket(
              addr_info[0], addr_info[1], addr_info[2]
          )
      except OSError:
          continue

      connect_host = addr_info[-1][0]
      if port == 8883:
          sock = self._ssl_context.wrap_socket(sock, server_hostname=host)
          connect_host = host
      sock.settimeout(timeout)

      try:
          sock.connect((connect_host, port))
      except MemoryError:
          sock.close()
          sock = None
      except OSError:
          sock.close()
          sock = None

  if sock is None:
      raise RuntimeError("Repeated socket failures")
tannewt commented 3 years ago

Ah, so it's coming from connect. I think those are usually a result of not being able to allocate the SSL buffers from the IDF. There are likely IDF memory debugging settings that could help debug this.