diff options
author | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2016-05-15 22:14:12 +0300 |
---|---|---|
committer | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2016-05-15 22:42:12 +0300 |
commit | afce978aca77805e84a2442c93c26dab045784f8 (patch) | |
tree | 2fb23380f45cb717de7245f0996e554894a05356 /extmod | |
parent | ca63c770733ead7fd5de061ddc5268ffbd3c368b (diff) | |
download | micropython-afce978aca77805e84a2442c93c26dab045784f8.tar.gz micropython-afce978aca77805e84a2442c93c26dab045784f8.zip |
extmod/modlwip: Rework how Python accept callback is called.
Calling it from lwIP accept callback will lead incorrect functioning
and/or packet leaks if Python callback has any networking calls, due
to lwIP non-reentrancy. So, instead schedule "poll" callback to do
that, which will be called by lwIP when it does not perform networking
activities. "Poll" callback is called infrequently though (docs say
every 0.5s by default), so for better performance, lwIP needs to be
patched to call poll callback soon after accept callback, but when
current packet is already processed.
Diffstat (limited to 'extmod')
-rw-r--r-- | extmod/modlwip.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/extmod/modlwip.c b/extmod/modlwip.c index e03bdd56ff..cb7cc6596f 100644 --- a/extmod/modlwip.c +++ b/extmod/modlwip.c @@ -311,6 +311,17 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb return ERR_BUF; } +// "Poll" (idle) callback to be called ASAP after accept callback +// to execute Python callback function, as it can't be executed +// from accept callback itself. +STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb) +{ + lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; + tcp_poll(pcb, NULL, 0); + exec_user_callback(socket); + return ERR_OK; +} + // Callback for incoming tcp connections. STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg; @@ -323,7 +334,12 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) { return ERR_BUF; } else { socket->incoming.connection = newpcb; - exec_user_callback(socket); + if (socket->callback != MP_OBJ_NULL) { + // Schedule accept callback to be called when lwIP is done + // with processing this incoming connection on its side and + // is idle. + tcp_poll(newpcb, _lwip_tcp_accept_finished, 1); + } return ERR_OK; } } |