drivers: net: nsos: update unwatched file descriptor with poll()

zsock_poll_internal() iterates through all fds to call
ZFD_IOCTL_POLL_UPDATE on them. In cases when -EAGAIN is returned from one
of such syscalls (which happens for example for TLS sockets when in the
middle of a TLS handshake) whole fds array is iterated once again. This
means that ZFD_IOCTL_POLL_UPDATE can be called more than once for a single
preceding ZFD_IOCTL_POLL_PREPARE operation. This resulted in error in
nsos_adapt_poll_remove() call, which was not intended to be called twice.

In case ZFD_IOCTL_POLL_UPDATE is called second time, update 'revents' just
by calling poll() syscall on the host (Linux) side with 0 timeout.

Signed-off-by: Marcin Niestroj <m.niestroj@emb.dev>
diff --git a/drivers/net/nsos.h b/drivers/net/nsos.h
index 14b4951..e7ece3d 100644
--- a/drivers/net/nsos.h
+++ b/drivers/net/nsos.h
@@ -113,6 +113,7 @@
 
 void nsos_adapt_poll_add(struct nsos_mid_pollfd *pollfd);
 void nsos_adapt_poll_remove(struct nsos_mid_pollfd *pollfd);
+void nsos_adapt_poll_update(struct nsos_mid_pollfd *pollfd);
 
 int nsos_adapt_fcntl_getfl(int fd);
 int nsos_adapt_fcntl_setfl(int fd, int flags);
diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c
index 9c8184b..5f44b33 100644
--- a/drivers/net/nsos_adapt.c
+++ b/drivers/net/nsos_adapt.c
@@ -533,6 +533,25 @@
 	nsos_adapt_nfds--;
 }
 
+void nsos_adapt_poll_update(struct nsos_mid_pollfd *pollfd)
+{
+	struct pollfd fds = {
+		.fd = pollfd->fd,
+		.events = pollfd->events,
+	};
+	int ret;
+
+	ret = poll(&fds, 1, 0);
+	if (ret < 0) {
+		nsi_print_error_and_exit("error in poll(): errno=%d\n", errno);
+		return;
+	}
+
+	if (ret > 0) {
+		pollfd->revents = fds.revents;
+	}
+}
+
 struct nsos_addrinfo_wrap {
 	struct nsos_mid_addrinfo addrinfo_mid;
 	struct nsos_mid_sockaddr_storage addr_storage;
diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c
index 98d6c42..2e1ff45 100644
--- a/drivers/net/nsos_sockets.c
+++ b/drivers/net/nsos_sockets.c
@@ -298,6 +298,11 @@
 	signaled = 0;
 	flags = 0;
 
+	if (!sys_dnode_is_linked(&sock->node)) {
+		nsos_adapt_poll_update(&sock->pollfd);
+		return 0;
+	}
+
 	nsos_adapt_poll_remove(&sock->pollfd);
 	sys_dlist_remove(&sock->node);