Skip to content

Commit 07ce1fa

Browse files
committed
Merge pull request #1103 from pguyot/w10/fix-esp32-socket_driver
Fix several issues in esp32 socket_driver (default gen_* implementation) Fix avail_bytes that was not initialized Fix handling of read condition messages (netconn with NETCONN_EVT_RCVPLUS and len == 0) Fix a race condition where two netconn_evt would be processed by a single netconn_recv and the second netconn_recv would block This makes test_socket work much more reliably on a physical esp32c3 These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license). SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
2 parents 172847c + 3a09b8b commit 07ce1fa

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- Fix a bug that broke sockets on ESP32-C3 and other single core ESP32 devices, that may also
1212
cause other issues. The bug has been introduced with messages from tasks change between beta.1
1313
and rc.0
14+
- Fixed several issues related to Esp32 socket_driver that made it unreliable, especially with
15+
single core MCUs
1416

1517
## [0.6.0-rc.0] - 2024-03-03
1618

src/platforms/esp32/components/avm_builtins/socket_driver.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ struct SocketData
170170
size_t buffer;
171171
bool active : 1;
172172
bool binary : 1;
173+
bool read_condition : 1;
173174
};
174175

175176
struct TCPClientSocketData
@@ -237,6 +238,10 @@ void IRAM_ATTR socket_callback(struct netconn *netconn, enum netconn_evt evt, u1
237238
TRACE("socket_callback netconn=%p, evt=%d, len=%d\n", (void *) netconn, evt, len);
238239

239240
// We only listen to NETCONN_EVT_RCVPLUS events
241+
// NETCONN_EVT_RCVPLUS means it's safe to perform a potentially call once
242+
// more. However, two data events (with len > 0) may be processed by a single
243+
// netconn_recv. So we're sending len as well to address the case where len
244+
// is equal to 0 and netconn_recv will return an error.
240245
if (evt == NETCONN_EVT_RCVPLUS) {
241246
struct NetconnEvent event;
242247
event.netconn = netconn;
@@ -362,8 +367,10 @@ static void socket_data_init(struct SocketData *data, Context *ctx, struct netco
362367
data->process_id = ctx->process_id;
363368
data->controlling_process_pid = 0;
364369
data->port = 0;
370+
data->avail_bytes = 0;
365371
data->active = true;
366372
data->binary = true;
373+
data->read_condition = false;
367374
data->buffer = 512;
368375

369376
list_append(sockets, &data->sockets_head);
@@ -679,6 +686,7 @@ static NativeHandlerResult do_receive_data(Context *ctx)
679686
return NativeContinue;
680687
}
681688
socket_data->avail_bytes -= data_len;
689+
socket_data->read_condition = false;
682690

683691
TRACE("%*s\n", (int) data_len, (char *) data);
684692

@@ -781,9 +789,22 @@ static NativeHandlerResult do_data_netconn_event(Context *ctx, int len)
781789
TRACE("do_data_netconn_event\n");
782790
struct SocketData *socket_data = ctx->platform_data;
783791

792+
socket_data->avail_bytes += len;
793+
794+
// We got a message saying that it's safe to call netconn_recv as it will
795+
// not block yet there is no data.
796+
if (len == 0) {
797+
socket_data->read_condition = true;
798+
}
799+
800+
// If socket is in passive mode but we don't have any waiting receiver, we
801+
// should just increment the number of available bytes.
784802
if (!socket_data->active && socket_data->passive_receiver_process_pid == 0) {
785-
// netconn_recv will not block
786-
socket_data->avail_bytes += len;
803+
return NativeContinue;
804+
}
805+
806+
// We may have already read the bytes from this event
807+
if (socket_data->avail_bytes <= 0 && !socket_data->read_condition) {
787808
return NativeContinue;
788809
}
789810
return do_receive_data(ctx);
@@ -1249,11 +1270,12 @@ static NativeHandlerResult do_recvfrom(Context *ctx, const GenMessage *gen_messa
12491270
socket_data->passive_receiver_process_pid = pid;
12501271
socket_data->passive_ref_ticks = ref_ticks;
12511272

1252-
if (socket_data->avail_bytes > 0) {
1253-
return do_receive_data(ctx);
1273+
// There may be nothing to read.
1274+
if (socket_data->avail_bytes <= 0 && !socket_data->read_condition) {
1275+
return NativeContinue;
12541276
}
12551277

1256-
return NativeContinue;
1278+
return do_receive_data(ctx);
12571279
}
12581280

12591281
static void do_get_port(Context *ctx, const GenMessage *gen_message)

0 commit comments

Comments
 (0)