Skip to content

Commit 894d7a5

Browse files
committed
extmod/modlwip: Fix latent bug with partially created socket object.
Sockets have a finaliser, so they must be created carefully. Signed-off-by: Damien George <damien@micropython.org>
1 parent f918e33 commit 894d7a5

1 file changed

Lines changed: 11 additions & 9 deletions

File tree

extmod/modlwip.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,23 +1091,17 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
10911091
mp_raise_OSError(MP_EOPNOTSUPP);
10921092
}
10931093

1094-
// Create new socket object, do it here because we must not raise an out-of-memory
1095-
// exception when the LWIP concurrency lock is held
1096-
lwip_socket_obj_t *socket2 = mp_obj_malloc_with_finaliser(lwip_socket_obj_t, &lwip_socket_type);
1097-
10981094
MICROPY_PY_LWIP_ENTER
10991095

11001096
if (socket->pcb.tcp == NULL) {
11011097
MICROPY_PY_LWIP_EXIT
1102-
m_del_obj(lwip_socket_obj_t, socket2);
11031098
mp_raise_OSError(MP_EBADF);
11041099
}
11051100

11061101
// I need to do this because "tcp_accepted", later, is a macro.
11071102
struct tcp_pcb *listener = socket->pcb.tcp;
11081103
if (listener->state != LISTEN) {
11091104
MICROPY_PY_LWIP_EXIT
1110-
m_del_obj(lwip_socket_obj_t, socket2);
11111105
mp_raise_OSError(MP_EINVAL);
11121106
}
11131107

@@ -1124,7 +1118,6 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
11241118
}
11251119
if (socket_is_timedout(socket, ticks_start)) {
11261120
MICROPY_PY_LWIP_EXIT
1127-
m_del_obj(lwip_socket_obj_t, socket2);
11281121
if (socket->timeout == 0) {
11291122
mp_raise_OSError(MP_EAGAIN);
11301123
} else {
@@ -1135,24 +1128,33 @@ static mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
11351128
}
11361129

11371130
// We get a new pcb handle...
1138-
socket2->pcb.tcp = *incoming_connection;
1131+
struct tcp_pcb *pcb_new = *incoming_connection;
11391132
if (++socket->incoming.connection.iget >= socket->incoming.connection.alloc) {
11401133
socket->incoming.connection.iget = 0;
11411134
}
11421135
*incoming_connection = NULL;
11431136

1137+
MICROPY_PY_LWIP_EXIT
1138+
11441139
// ...and set up the new socket for it.
1140+
//
1141+
// Creating the new socket object must be done in one step due to the finaliser, and
1142+
// outside the lwIP concurrency lock in case it raises an out-of-memory exception.
1143+
lwip_socket_obj_t *socket2 = mp_obj_malloc_with_finaliser(lwip_socket_obj_t, &lwip_socket_type);
1144+
socket2->pcb.tcp = pcb_new;
11451145
socket2->domain = MOD_NETWORK_AF_INET;
11461146
socket2->type = MOD_NETWORK_SOCK_STREAM;
11471147
socket2->incoming.tcp.pbuf = NULL;
11481148
socket2->timeout = socket->timeout;
11491149
socket2->state = STATE_CONNECTED;
11501150
socket2->recv_offset = 0;
11511151
socket2->callback = MP_OBJ_NULL;
1152+
1153+
MICROPY_PY_LWIP_REENTER
1154+
11521155
tcp_arg(socket2->pcb.tcp, (void *)socket2);
11531156
tcp_err(socket2->pcb.tcp, _lwip_tcp_error);
11541157
tcp_recv(socket2->pcb.tcp, _lwip_tcp_recv);
1155-
11561158
tcp_accepted(listener);
11571159

11581160
MICROPY_PY_LWIP_EXIT

0 commit comments

Comments
 (0)