net: sockets: Fix recv() not being interrupted on close()

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>
diff --git a/subsys/net/lib/sockets/sockets.c b/subsys/net/lib/sockets/sockets.c
index b3011e0..660b64d 100644
--- a/subsys/net/lib/sockets/sockets.c
+++ b/subsys/net/lib/sockets/sockets.c
@@ -154,6 +154,9 @@
 
 	/* 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)
@@ -262,6 +265,9 @@
 		(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));
@@ -418,7 +424,7 @@
 		(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);
 }
 
@@ -434,9 +440,6 @@
 		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 {
@@ -1151,6 +1154,8 @@
 
 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()
@@ -1163,8 +1168,15 @@
 
 	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;