adafruit / circuitpython

CircuitPython - a Python implementation for teaching coding with microcontrollers
https://circuitpython.org
Other
4.1k stars 1.22k forks source link

Getting a `Hard fault` when using SSL with a WIZnet5k #9317

Open justmobilize opened 5 months ago

justmobilize commented 5 months ago

CircuitPython version

Adafruit CircuitPython 9.1.0-beta.3 on 2024-05-22; FeatherS3 with ESP32S3

Code/REPL

import alarm
import board
import busio
import digitalio
import time

import adafruit_connection_manager
import adafruit_requests
from adafruit_wiznet5k import adafruit_wiznet5k

# delay so you can connect
print("starting:", end="")
for i in range(10):
    print(".", end="")
    time.sleep(1)
print()

print("getting radio")
chip_select = digitalio.DigitalInOut(board.D10)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
radio = adafruit_wiznet5k.WIZNET5K(spi, chip_select, is_dhcp=True)

print("getting pool, ssl, requets")
pool = adafruit_connection_manager.get_radio_socketpool(radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio)
requests = adafruit_requests.Session(pool, ssl_context)

print("getting quotes")
test_url = "http://www.adafruit.com/api/quotes.php"
with requests.get(test_url) as response:
    result = response.text
print(result)

print("sleeping")
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 5)
alarm.exit_and_deep_sleep_until_alarms(time_alarm)

Behavior

$ tio /dev/ttyS7
[09:18:09.074] tio v2.6
[09:18:09.076] Press ctrl-t q to quit
[09:18:09.092] Warning: Could not open tty device (No such device or address)
[09:18:09.093] Waiting for tty device..
[09:18:15.151] Connected
.........
getting radio
getting pool, ssl, requets
getting quotes
[{"text":"... when you see something that is not right, not fair, not just, say something, do something. Get in trouble, good trouble, necessary trouble","author":"John Lewis"}]
sleeping

Code done running.

[09:18:29.717] Disconnected
[09:18:29.745] Error: select() failed (Permission denied)

justi@jmStudio MSYS ~
$ tio /dev/ttyS7
[09:19:06.530] tio v2.6
[09:19:06.532] Press ctrl-t q to quit
[09:19:06.552] Connected
Auto-reload is off.
Running in safe mode! Not running saved code.

You are in safe mode because:
CircuitPython core code crashed hard. Whoops!
Hard fault: memory access or instruction error.
Please file an issue with your program at github.com/adafruit/circuitpython/issues.
Press reset to exit safe mode.

Press any key to enter the REPL. Use CTRL-D to reload.

Description

No response

Additional information

No response

justmobilize commented 5 months ago

I will note, that this is specific to the new feature in 9.1.0 that allows SSL to be used with the WIZnet5k

jepler commented 5 months ago

note, for those who wondered: that particular URL redirects to https:, so this is using https even though the url is http

justmobilize commented 5 months ago

@jepler the same thing happens if it starts as https:. Should I update the example?

My assumption (although probably totally wrong) is that some resource is still being held onto by python when the fake sleep happens

justmobilize commented 5 months ago

and verified. This doesn't crash:

import alarm
import board
import busio
import digitalio
import time

import adafruit_connection_manager
import adafruit_requests
from adafruit_wiznet5k import adafruit_wiznet5k

# delay so you can connect
print("starting:", end="")
for i in range(10):
    print(".", end="")
    time.sleep(1)
print()

print("getting radio")
chip_select = digitalio.DigitalInOut(board.D10)
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
radio = adafruit_wiznet5k.WIZNET5K(spi, chip_select, is_dhcp=True)

print("getting pool, ssl, requets")
pool = adafruit_connection_manager.get_radio_socketpool(radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(radio)
requests = adafruit_requests.Session(pool, ssl_context)

print("getting quotes")
test_url = "http://www.adafruit.com/api/quotes.php"
with requests.get(test_url) as response:
    result = response.text
print(result)

adafruit_connection_manager.connection_manager_close_all(release_references=True)

print("sleeping")
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + 5)
alarm.exit_and_deep_sleep_until_alarms(time_alarm)
jepler commented 5 months ago

what if your code doesn't deep sleep, but just exits?

justmobilize commented 5 months ago

That works fine. So does supervisor.reload()

justmobilize commented 5 months ago

I was wrong, still had the old code. It fails the same way with both.

justmobilize commented 5 months ago

Being even more specific, this fixes it:

#connection_manager_close_all()
connection_manager = adafruit_connection_manager._global_connection_managers.get(pool)
connection_manager._free_sockets(force=True)

So it's the open socket via the ssl_context