8000 extmod/modlwip: Protect socket.accept with lwIP concurrency lock. · rlucia/micropython@490e0f3 · GitHub
[go: up one dir, main page]

Skip to content

Commit 490e0f3

Browse files
committed
extmod/modlwip: Protect socket.accept with lwIP concurrency lock.
This is needed now that the accept queue can have pending connections removed asynchronously.
1 parent 2ec7838 commit 490e0f3

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

extmod/modlwip.c

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -859,42 +859,58 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_socket_listen_obj, lwip_socket_listen);
859859
STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
860860
lwip_socket_obj_t *socket = MP_OBJ_TO_PTR(self_in);
861861

862-
if (socket->pcb.tcp == NULL) {
863-
mp_raise_OSError(MP_EBADF);
864-
}
865862
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
866863
mp_raise_OSError(MP_EOPNOTSUPP);
867864
}
865+
866+
// Create new socket object, do it here because we must not raise an out-of-memory
867+
// exception when the LWIP concurrency lock is held
868+
lwip_socket_obj_t *socket2 = m_new_obj_with_finaliser(lwip_socket_obj_t);
869+
socket2->base.type = &lwip_socket_type;
870+
871+
MICROPY_PY_LWIP_ENTER
872+
873+
if (socket->pcb.tcp == NULL) {
874+
MICROPY_PY_LWIP_EXIT
875+
m_del_obj(lwip_socket_obj_t, socket2);
876+
mp_raise_OSError(MP_EBADF);
877+
}
878+
868879
// I need to do this because "tcp_accepted", later, is a macro.
869880
struct tcp_pcb *listener = socket->pcb.tcp;
870881
if (listener->state != LISTEN) {
882+
MICROPY_PY_LWIP_EXIT
883+
m_del_obj(lwip_socket_obj_t, socket2);
871884
mp_raise_OSError(MP_EINVAL);
872885
}
873886

874887
// accept incoming connection
875888
struct tcp_pcb *volatile *incoming_connection = &lwip_socket_incoming_array(socket)[socket->incoming.connection.iget];
876889
if (*incoming_connection == NULL) {
877890
if (socket->timeout == 0) {
891+
MICROPY_PY_LWIP_EXIT
892+
m_del_obj(lwip_socket_obj_t, socket2);
878893
mp_raise_OSError(MP_EAGAIN);
879894
} else if (socket->timeout != -1) {
880-
for (mp_uint_t retries = socket->timeout / 100; retries--;) {
895+
mp_uint_t retries = socket->timeout / 100;
896+
while (*incoming_connection == NULL) {
897+
MICROPY_PY_LWIP_EXIT
898+
if (retries-- == 0) {
899+
m_del_obj(lwip_socket_obj_t, socket2);
900+
mp_raise_OSError(MP_ETIMEDOUT);
901+
}
881902
mp_hal_delay_ms(100);
882-
if (*incoming_connection != NULL) break;
883-
}
884-
if (*incoming_connection == NULL) {
885-
mp_raise_OSError(MP_ETIMEDOUT);
903+
MICROPY_PY_LWIP_REENTER
886904
}
887905
} else {
888906
while (*incoming_connection == NULL) {
907+
MICROPY_PY_LWIP_EXIT
889908
poll_sockets();
909+
MICROPY_PY_LWIP_REENTER
890910
}
891911
}
892912
}
893913

894-
// create new socket object
895-
lwip_socket_obj_t *socket2 = m_new_obj_with_finaliser(lwip_socket_obj_t);
896-
socket2->base.type = &lwip_socket_type;
897-
898914
// We get a new pcb handle...
899915
socket2->pcb.tcp = *incoming_connection;
900916
if (++socket->incoming.connection.iget >= socket->incoming.connection.alloc) {
@@ -916,6 +932,8 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
916932

917933
tcp_accepted(listener);
918934

935+
MICROPY_PY_LWIP_EXIT
936+
919937
// make the return value
920938
uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];
921939
memcpy(ip, &(socket2->pcb.tcp->remote_ip), sizeof(ip));

0 commit comments

Comments
 (0)
0