On Raspberry Pi Pico W, socket `accept` hangs when started in a thread
On Raspberry Pi Pico W, sockets are broken when started in a thread.
Here is a minimal broken code, hanging on socket accept (at best 1st call works):
from machine import I2C, Pin
import network, time
import _thread
try:
import usocket as socket
except:
import socket
#WiFi
ssid = "MySSID"
wifikey = "MyKey"
door_state = "unknown"
def web_page():
html = """<html><head> <title>My minimal TEST</title></head><body> <h1>My minimal TEST</h1>
<p>Door state: <strong>""" + door_state + """</strong></p></body></html>"""
return html
mywifi = network.WLAN(network.STA_IF)
try:
mywifi.active(True)
mywifi.connect(ssid, wifikey)
except:
print('network config FAILED!')
for i in range(60):
if mywifi.isconnected():
print('network config:', mywifi.ifconfig())
break
else:
time.sleep(1) # Sleep for 1 second
def DummyLoop():
while True:
time.sleep(10)
def WebServer():
print("Starting webserver...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('', 80))
s.listen(5)
while True:
print('Webserver: Waiting on s.accept')
conn, addr = s.accept() # Blocked here forever...
print('Webserver: Got a connection from %s' % str(addr))
request = conn.recv(1024)
request = str(request)
print('Webserver: Content = %s' % request)
response = web_page()
conn.send('HTTP/1.1 200 OK\n')
conn.send('Content-Type: text/html\n')
conn.send('Connection: close\n\n')
conn.sendall(response)
conn.close()
print('Webserver: Conn.close')
_thread.start_new_thread(WebServer, ())
DummyLoop()
If I replace the last 2 lines with:
_thread.start_new_thread(DummyLoop, ())
WebServer()
to not start WebServer in a separate thread (Basically invert DummyLoop and WebServer), then, it just works.
MicroPython v1.21.0 on 2023-10-06; Raspberry Pi Pico W with RP2040
rp2: Accept not responding on Pico W after 5 mins
Port, board and/or hardware
Raspberry Pi Pico W
MicroPython version
MicroPython v1.23.0 on 2024-06-02; Raspberry Pi Pico W with RP2040
Reproduction
import network
import socket
import time
ssid = 'SSID'
password = 'PASSWORD'
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
while not wlan.isconnected():
time.sleep(1)
print("Connected", wlan.ifconfig()[0])
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(1)
while True:
cl, addr = s.accept()
request = cl.recv(1024)
cl.send("HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n")
cl.send("<html><body>{}</body></html>".format(time.time()))
cl.close()
Expected behaviour
I expected the Pico W to accept requests and respond with the time (single integer) indefinitely.
Observed behaviour
Running the example code (which is a simplified version of the webserver example on the RPI site) I can send requests from FIrefox to thePico W ip address and get an imediate response. If the Pico W is left about 5 minutes or more with receiving a request then it no longer appears to accept on he socket.
Additional Information
If I put a timeout on the socket of 30 seconds the Pico W works for longer than 5 minutes but does eventually stop responding.
Putting a line into the html so that it refeshes every minute will keep the Pico responding for hours.
Code of Conduct
Yes, I agree