Skip to content

Commit 69d9eb6

Browse files
jukkarnashif
authored andcommitted
net: socket: Wait new buffers when sending
If we run out of network buffers and cannot send data, and if we have a blocking socket, then wait until new buffers are available before returning. As this might lead to deadlock, wait only max 10 seconds and return ENOMEM if we cannot get buffers in a reasonable amount of time. Fixes #28216 Signed-off-by: Jukka Rissanen <[email protected]>
1 parent 80d0461 commit 69d9eb6

File tree

1 file changed

+38
-11
lines changed

1 file changed

+38
-11
lines changed

subsys/net/lib/sockets/sockets.c

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -575,15 +575,21 @@ static inline int z_vrfy_zsock_accept(int sock, struct sockaddr *addr,
575575
#include <syscalls/zsock_accept_mrsh.c>
576576
#endif /* CONFIG_USERSPACE */
577577

578+
#define WAIT_BUFS K_MSEC(100)
579+
#define MAX_WAIT_BUFS K_SECONDS(10)
580+
578581
ssize_t zsock_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
579582
int flags,
580583
const struct sockaddr *dest_addr, socklen_t addrlen)
581584
{
582585
k_timeout_t timeout = K_FOREVER;
586+
uint64_t buf_timeout = 0;
583587
int status;
584588

585589
if ((flags & ZSOCK_MSG_DONTWAIT) || sock_is_nonblock(ctx)) {
586590
timeout = K_NO_WAIT;
591+
} else {
592+
buf_timeout = z_timeout_end_calc(MAX_WAIT_BUFS);
587593
}
588594

589595
/* Register the callback before sending in order to receive the response
@@ -596,18 +602,39 @@ ssize_t zsock_sendto_ctx(struct net_context *ctx, const void *buf, size_t len,
596602
return -1;
597603
}
598604

599-
if (dest_addr) {
600-
status = net_context_sendto(ctx, buf, len, dest_addr,
601-
addrlen, NULL, timeout,
602-
ctx->user_data);
603-
} else {
604-
status = net_context_send(ctx, buf, len, NULL, timeout,
605-
ctx->user_data);
606-
}
605+
while (1) {
606+
if (dest_addr) {
607+
status = net_context_sendto(ctx, buf, len, dest_addr,
608+
addrlen, NULL, timeout,
609+
ctx->user_data);
610+
} else {
611+
status = net_context_send(ctx, buf, len, NULL, timeout,
612+
ctx->user_data);
613+
}
607614

608-
if (status < 0) {
609-
errno = -status;
610-
return -1;
615+
if (status < 0) {
616+
if (status == -ENOBUFS &&
617+
K_TIMEOUT_EQ(timeout, K_FOREVER)) {
618+
/* If we cannot get any buffers in reasonable
619+
* amount of time, then do not wait forever as
620+
* there might be some bigger issue.
621+
*/
622+
int64_t remaining = buf_timeout - z_tick_get();
623+
624+
if (remaining <= 0) {
625+
errno = ENOMEM;
626+
return -1;
627+
}
628+
629+
k_sleep(WAIT_BUFS);
630+
continue;
631+
} else {
632+
errno = -status;
633+
return -1;
634+
}
635+
}
636+
637+
break;
611638
}
612639

613640
return status;

0 commit comments

Comments
 (0)