lwIP sockets: a failed listen or connect leaves the socket lock held, a later close hangs forever
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 84/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- c, erlang
- Domain
- embedded-iot
Research direction
Start in src/libAtomVM/otp_socket.c and read nif_socket_listen and the lwIP branch of nif_socket_connect. Check how #2345 handles the socket lock on the tcp_close error path, then reproduce the failed listen or connect on an SMP RP2 build. Done when each error path releases the read lock and socket:close returns after the failure.
Written by the indexing model from the issue text.
Description
Affected: release-0.7 at ca1583068, lwIP socket backend (RP2 port), SMP builds
(the default on RP2). Not changed by #2345.
What happens
nif_socket_listen and nif_socket_connect take the socket read lock, then
return on an lwIP error without releasing it:
nif_socket_listen:if (new_pcb == NULL) { return make_lwip_err_tuple(err, ctx); }nif_socket_connect(lwIP branch):if (err != ERR_OK) { ... return {error, closed} / RAISE_ERROR(...) }
The read lock is never released. Every later operation that takes the write lock
on that socket blocks forever and pins a scheduler thread: socket:close/1,
socket:recv/1,2,3, socket:accept/1,2, socket:send/2 (through the select
NIFs) and the monitor callback socket_down.
How to reproduce (Pico W)
Connect, with the network down or no route to the address (tcp_connect fails
with ERR_RTE):
{ok, S} = socket:open(inet, stream, tcp),
{error, closed} = socket:connect(S, #{family => inet, addr => {192, 168, 0, 1}, port => 80}),
ok = socket:close(S). % never returns
Listen on a socket that is already connected (tcp_listen fails with ERR_CLSD):
{error, _} = socket:listen(ConnectedSocket),
ok = socket:close(ConnectedSocket). % never returns
Where
src/libAtomVM/otp_socket.c, nif_socket_listen and nif_socket_connect,
#elif OTP_SOCKET_LWIP branches.
Suggested fix
SMP_RWLOCK_UNLOCK(rsrc_obj->socket_lock) before returning on both error
paths, as #2345 did for the failing tcp_close in nif_socket_close.
- Dominant language
- Erlang
- Stars
- 2.3k
- Forks
- 171
- Avg merge
- 4d 11h
- Merged PRs (30d)
- 20
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from atomvm/AtomVM
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
Maintainers usually reply within 3 days
Similar issues
-
SPIDevice selects an active-high device as soon as it is createdPossibly taken @mikeysklar claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
adafruit/circuitpython#11869 ·
Maintainers usually reply within 1 day
-
backlog bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
EchoTools/nevr-runtime#2664 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
seven-lynx/HoundMind#108 ·
Maintainers usually reply within 1 day
-
Type: Bug USB-650
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
espressif/esp-usb#650 · 2 comments ·
Maintainers usually reply within 2 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100