Skip to content

Commit 1184089

Browse files
jukkarnashif
authored andcommitted
net: sockets: Add locking to receive callback
Fix a regression when application is waiting data but does not notice that because socket layer is not woken up. This could happen because application was waiting condition variable but the signal to wake the condvar came before the wait started. Normally if there is constant flow of incoming data to the socket, the signal would be given later. But if the peer is waiting that Zephyr replies, there might be a timeout at peer. The solution is to add locking in socket receive callback so that we only signal the condition variable after we have made sure that the condition variable is actually waiting the data. Fixes #34964 Signed-off-by: Jukka Rissanen <[email protected]>
1 parent 7986cae commit 1184089

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

subsys/net/lib/sockets/sockets.c

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ static void zsock_received_cb(struct net_context *ctx,
344344
int status,
345345
void *user_data)
346346
{
347+
if (ctx->cond.lock) {
348+
(void)k_mutex_lock(ctx->cond.lock, K_FOREVER);
349+
}
350+
347351
NET_DBG("ctx=%p, pkt=%p, st=%d, user_data=%p", ctx, pkt, status,
348352
user_data);
349353

@@ -364,8 +368,7 @@ static void zsock_received_cb(struct net_context *ctx,
364368
NET_DBG("Set EOF flag on pkt %p", last_pkt);
365369
}
366370

367-
(void)k_condvar_signal(&ctx->cond.recv);
368-
return;
371+
goto unlock;
369372
}
370373

371374
/* Normal packet */
@@ -379,6 +382,11 @@ static void zsock_received_cb(struct net_context *ctx,
379382

380383
k_fifo_put(&ctx->recv_q, pkt);
381384

385+
unlock:
386+
if (ctx->cond.lock) {
387+
(void)k_mutex_unlock(ctx->cond.lock);
388+
}
389+
382390
/* Let reader to wake if it was sleeping */
383391
(void)k_condvar_signal(&ctx->cond.recv);
384392
}
@@ -964,15 +972,13 @@ static int wait_data(struct net_context *ctx, k_timeout_t *timeout)
964972
* lock at this point so skip it.
965973
*/
966974
NET_WARN("No lock pointer set for context %p", ctx);
975+
return -EINVAL;
976+
}
967977

968-
} else if (!k_fifo_peek_head(&ctx->recv_q)) {
969-
int ret;
970-
978+
if (k_fifo_is_empty(&ctx->recv_q)) {
971979
/* Wait for the data to arrive but without holding a lock */
972-
ret = k_condvar_wait(&ctx->cond.recv, ctx->cond.lock, *timeout);
973-
if (ret < 0) {
974-
return ret;
975-
}
980+
return k_condvar_wait(&ctx->cond.recv, ctx->cond.lock,
981+
*timeout);
976982
}
977983

978984
return 0;

0 commit comments

Comments
 (0)