Skip to content

Commit

Permalink
net: sockets: Fix recv() not being interrupted on close()
Browse files Browse the repository at this point in the history
In case recv() call was waiting for data, and the socket was closed from
another thread, the recv() call would not be interrupted, causing the
receiving thread to be blocked indefinitely.

Fix this, by signalling the condvar the recv() call is waiting on
close(). Additionally, close will now set the socket into error mode,
with EINTR as the error condition, allowing the blocked calls to
recognise that the call was interrupted, and return a proper error code
on the event.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
  • Loading branch information
rlubos authored and nashif committed May 26, 2023
1 parent 1d5b3af commit 966eff6
Showing 1 changed file with 18 additions and 6 deletions.
24 changes: 18 additions & 6 deletions subsys/net/lib/sockets/sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ static void zsock_flush_queue(struct net_context *ctx)

/* Some threads might be waiting on recv, cancel the wait */
k_fifo_cancel_wait(&ctx->recv_q);

/* Wake reader if it was sleeping */
(void)k_condvar_signal(&ctx->cond.recv);
}

#if defined(CONFIG_NET_NATIVE)
Expand Down Expand Up @@ -262,6 +265,9 @@ int zsock_close_ctx(struct net_context *ctx)
(void)net_context_recv(ctx, NULL, K_NO_WAIT, NULL);
}

ctx->user_data = INT_TO_POINTER(EINTR);
sock_set_error(ctx);

zsock_flush_queue(ctx);

SET_ERRNO(net_context_put(ctx));
Expand Down Expand Up @@ -418,7 +424,7 @@ static void zsock_received_cb(struct net_context *ctx,
(void)k_mutex_unlock(ctx->cond.lock);
}

/* Let reader to wake if it was sleeping */
/* Wake reader if it was sleeping */
(void)k_condvar_signal(&ctx->cond.recv);
}

Expand All @@ -434,9 +440,6 @@ int zsock_shutdown_ctx(struct net_context *ctx, int how)
sock_set_eof(ctx);

zsock_flush_queue(ctx);

/* Let reader to wake if it was sleeping */
(void)k_condvar_signal(&ctx->cond.recv);
} else if (how == ZSOCK_SHUT_WR || how == ZSOCK_SHUT_RDWR) {
SET_ERRNO(-ENOTSUP);
} else {
Expand Down Expand Up @@ -1151,6 +1154,8 @@ void net_socket_update_tc_rx_time(struct net_pkt *pkt, uint32_t end_tick)

int zsock_wait_data(struct net_context *ctx, k_timeout_t *timeout)
{
int ret;

if (ctx->cond.lock == NULL) {
/* For some reason the lock pointer is not set properly
* when called by fdtable.c:z_finalize_fd()
Expand All @@ -1163,8 +1168,15 @@ int zsock_wait_data(struct net_context *ctx, k_timeout_t *timeout)

if (k_fifo_is_empty(&ctx->recv_q)) {
/* Wait for the data to arrive but without holding a lock */
return k_condvar_wait(&ctx->cond.recv, ctx->cond.lock,
*timeout);
ret = k_condvar_wait(&ctx->cond.recv, ctx->cond.lock,
*timeout);
if (ret < 0) {
return ret;
}

if (sock_is_error(ctx)) {
return -POINTER_TO_INT(ctx->user_data);
}
}

return 0;
Expand Down

0 comments on commit 966eff6

Please sign in to comment.