adafruit / circuitpython

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

Pico-W: Setting wifi.radio.dns sends device into safe-mode #9726

Open bablokb opened 11 hours ago

bablokb commented 11 hours ago

CircuitPython version

Adafruit CircuitPython 9.2.0-beta.1 on 2024-10-11; Raspberry Pi Pico W with rp2040

Code/REPL

#import helpers
#helpers.connect()  connect to AP with wifi.radio.connect
import wifi
wifi.radio.dns
wifi.radio.dns = ('8.8.8.8',)

Behavior

>>> import helpers
>>> helpers.connect()
connecting to AP wlan-xxx ...
  connected: False
Unbekannter Fehler 205
  connected: True
>>> import wifi
>>> wifi.radio.dns
('10.1.2.1',)
>>> wifi.radio.dns = ('8.8.8.8',)

[16:30:07.695] Disconnected
[16:30:08.697] Warning: Could not open tty device (No such file or directory)
[16:30:08.697] Waiting for tty device..
[16:30:10.699] Warning: Could not open tty device (Permission denied)
[16:30:10.699] Waiting for tty device..
[16:30:11.703] Connected
Automatisches Neuladen ist deaktiviert.
Sicherheitsmodus aktiv! Gespeicherter Code wird nicht ausgeführt

Sie befinden sich im abgesicherten Modus, weil:
Der CircuitPython-Kerncode ist hart abgestürzt. Hoppla!
Hard fault: memory access or instruction error.
Reiche bitte ein Problem mit deinem Programm bei github.com/adafruit/circuitpython/issues ein.
Drücke Reset, um den Sicherheitsmodus zu beenden.

Drücke eine beliebige Taste um REPL zu betreten. Drücke STRG-D zum neuladen.

Adafruit CircuitPython 9.2.0-beta.1 on 2024-10-11; Raspberry Pi Pico W with rp2040
>>> 

Description

When setting wifi.radio.dns the device goes into safe-mode.

BTW: setting with wifi.radio.dns = ["8.8.8.8"] is even worse, the system does not even boot and reconnect again.

As a side note: the documentation of wifi.radio.dns could be more explicit about the argument: it is currently documented as Sequence[str], but in fact it must be currently a sequence of length zero or one. Also, think about the consistency of the API: all other methods of wifi.radio that take an IP as argument expect an instance of ipaddress.IPv4Address.

Additional information

No response

jepler commented 9 hours ago

The reason wifi.radio.dns is different is that it can support IPv6 addresses, and is even prepared to support multiple DNS servers when the underlying IP stack supports it as well. That said, it's clearly a bug when setting the property causes a crash.

It would be useful to know if setting the ipv4_dns property, which does have to be an IPV4Address, is also crashing; and it might serve as a workaround for you in your code.

jepler commented 9 hours ago

Looks like maybe a conversion to char * is missing, and not caught by the compiler. If you're able to build circuitpython please try with:

diff --git a/ports/raspberrypi/common-hal/wifi/Radio.c b/ports/raspberrypi/common-hal/wifi/Radio.c
index 3250ed4d7c..b34a7670b8 100644
--- a/ports/raspberrypi/common-hal/wifi/Radio.c
+++ b/ports/raspberrypi/common-hal/wifi/Radio.c
@@ -574,7 +574,7 @@ void common_hal_wifi_radio_set_dns(wifi_radio_obj_t *self, mp_obj_t dns_addrs_ob
         addr.addr = IPADDR_NONE;
     } else {
         mp_obj_t dns_addr_obj = mp_obj_subscr(dns_addrs_obj, MP_OBJ_NEW_SMALL_INT(0), MP_OBJ_SENTINEL);
-        socketpool_resolve_host_raise(dns_addr_obj, &addr);
+        socketpool_resolve_host_raise(mp_obj_str_get_str(dns_addr_obj), &addr);
     }
     dns_setserver(0, &addr);
 }
jepler commented 7 hours ago

You can also test with an artifact from the actions on #9727 if you have time