From #10615 (comment):
The PR seems like a rational fix, so maybe completely unrelated, but under atypically extreme duress (hammering on TCP socket, and hammering on interrupts ...assuming the code is doing what I think), a TCP client will get hardfaults somewhat regularly with PR artifacts on Pico W:
Client code (on a Pico W):
# Adafruit CircuitPython 10.0.0-beta.3 on 2025-08-29; Raspberry Pi Pico W with rp2040
# Adafruit CircuitPython 10.0.0-beta.3-8-g9e7a03cbc2 on 2025-09-05; Raspberry Pi Pico W with rp2040
# "Hard fault: memory access or instruction error." (after "Connecting")
import time
import supervisor
import microcontroller
import os
import random
import traceback
import wifi
import socketpool
import array
import pulseio
import board
# edit host and port to match server
HOST = "192.168.6.57"
PORT = 5000
TIMEOUT = 1
INTERVAL = 0.1
MAXBUF = 8192
def send_pulses():
# on off on ...
MAX_TRAIN = 17
for p_out in range(1, len(pulse_outs)):
p_train = []
for p_item in range(0, random.randint(3, MAX_TRAIN)):
p_train.append(random.randint(100, 10_000))
pulses = array.array('H', p_train)
pulse_outs[p_out].send(pulses)
time.sleep(3) # wait for serial after reset
print("Connecting to Wifi")
while not wifi.radio.connected:
try:
wifi.radio.connect(os.getenv('WIFI_SSID'), os.getenv('WIFI_PASSWORD'))
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
time.sleep(1 + random.random())
supervisor.reload()
# microcontroller.reset()
pool = socketpool.SocketPool(wifi.radio)
print(wifi.radio.ipv4_address)
# 50% duty cycle at 38kHz.
pulse_outs = []
pulse_outs.append(pulseio.PulseOut(board.GP0, frequency=38000, duty_cycle=32768))
pulse_outs.append(pulseio.PulseOut(board.GP1, frequency=38000, duty_cycle=32768))
pulse_outs.append(pulseio.PulseOut(board.GP2, frequency=38000, duty_cycle=32768))
pulse_outs.append(pulseio.PulseOut(board.GP3, frequency=38000, duty_cycle=32768))
buf = bytearray(MAXBUF)
while True:
try:
print("Create TCP Client Socket")
with pool.socket(pool.AF_INET, pool.SOCK_STREAM) as s:
s.settimeout(TIMEOUT)
print("Connecting")
s.connect((HOST, PORT))
payload = bytearray()
for _ in range(random.randint(0, MAXBUF)):
payload.append(random.choice((b'0123456789ABCDEF')))
send_pulses() #####
size = s.send(payload)
print("Sent", size, "bytes")
send_pulses() #####
size = s.recv_into(buf)
# occasionally on recv_into:
# OSError: [Errno 104] ECONNRESET
# OSError: [Errno 9] EBADF
# OSError: [Errno 116] ETIMEDOUT
print('Received', size, "bytes", buf[:size])
except Exception as ex:
print(f"⚠️", end=" ")
traceback.print_exception(ex, ex, ex.__traceback__)
time.sleep(INTERVAL)
Server code (on a Pico 2W):
import time
import microcontroller
import os
import random
import traceback
import wifi
import socketpool
HOST = ""
PORT = 5000
TIMEOUT = None
BACKLOG = 2
MAXBUF = 8192
time.sleep(3) # wait for serial after reset
print("Connecting to Wifi")
while not wifi.radio.connected:
try:
wifi.radio.connect(os.getenv('WIFI_SSID'), os.getenv('WIFI_PASSWORD'))
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
time.sleep(1)
microcontroller.reset()
pool = socketpool.SocketPool(wifi.radio)
print(wifi.radio.ipv4_address)
print("Create TCP Server socket", (HOST, PORT))
with pool.socket(pool.AF_INET, pool.SOCK_STREAM) as s:
s.setsockopt(pool.SOL_SOCKET, pool.SO_REUSEADDR, 1) #
s.settimeout(TIMEOUT)
s.bind((HOST, PORT))
s.listen(BACKLOG)
print("Listening")
buf = bytearray(MAXBUF)
while True:
try:
print("Accepting connections")
conn, addr = s.accept()
conn.settimeout(TIMEOUT)
print("Accepted from", addr)
size = conn.recv_into(buf, MAXBUF)
print("Received", buf[:size], size, "bytes")
conn.send(buf[:size])
print("Sent", buf[:size], size, "bytes")
except Exception as ex:
print(f"⚠️", end=" ")
traceback.print_exception(ex, ex, ex.__traceback__)
finally:
time.sleep(0.1) # too short and client gets "OSError: [Errno 104] ECONNRESET" in recv
conn.close()
With beta.3, hardfaults occur under less duress than above, but I hadn't actually replicated it with the prior testing in the previous comment, so just wanted to see how it could be triggered.
There also seems to be a situation where the server closing the connection immediately after sending the response can cause OSError: [Errno 104] ECONNRESET at the client (somehow before the client has read all of the incoming packet... some buffering issue?).
Originally posted by @anecdata in #10615 (comment)
From #10615 (comment):