net: tcp: Fix possible deadlock in tcp_conn_unref()

This reverts commit e7489d8de7.

And fixes the deadlock by allowing only 1 thread to actualy clean up
the connection when the ref_count is 0.

Signed-off-by: Daniel Nejezchleb <dnejezchleb@hwg.cz>
This commit is contained in:
Daniel Nejezchleb 2022-02-09 18:48:04 +01:00 committed by Carles Cufí
commit 1f22a2bc3c

View file

@ -377,15 +377,15 @@ static int tcp_conn_unref(struct tcp *conn)
}
#endif /* CONFIG_NET_TEST_PROTOCOL */
k_mutex_lock(&tcp_lock, K_FOREVER);
ref_count = atomic_dec(&conn->ref_count) - 1;
if (ref_count) {
if (ref_count != 0) {
tp_out(net_context_get_family(conn->context), conn->iface,
"TP_TRACE", "event", "CONN_DELETE");
goto unlock;
return ref_count;
}
k_mutex_lock(&tcp_lock, K_FOREVER);
/* If there is any pending data, pass that to application */
while ((pkt = k_fifo_get(&conn->recv_data, K_NO_WAIT)) != NULL) {
if (net_context_packet_received(
@ -403,10 +403,8 @@ static int tcp_conn_unref(struct tcp *conn)
}
if (conn->context->recv_cb) {
k_mutex_unlock(&tcp_lock);
conn->context->recv_cb(conn->context, NULL, NULL, NULL,
-ECONNRESET, conn->recv_user_data);
k_mutex_lock(&tcp_lock, K_FOREVER);
}
conn->context->tcp = NULL;
@ -431,7 +429,6 @@ static int tcp_conn_unref(struct tcp *conn)
k_mem_slab_free(&tcp_conns_slab, (void **)&conn);
unlock:
k_mutex_unlock(&tcp_lock);
out:
return ref_count;