public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 6/6] udp: Handle more error conditions in udp_sock_errs()
Date: Fri,  6 Sep 2024 15:17:10 +1000	[thread overview]
Message-ID: <20240906051710.3863211-7-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20240906051710.3863211-1-david@gibson.dropbear.id.au>

udp_sock_errs() reads out everything in the socket error queue.  However
we've seen some cases[0] where an EPOLLERR event is active, but there isn't
anything in the queue.

One possibility is that the error is reported instead by the SO_ERROR
sockopt.  Check for that case and report it as best we can.  If we still
get an EPOLLERR without visible error, we have no way to clear the error
state, so treat it as an unrecoverable error.

[0] https://github.com/containers/podman/issues/23686#issuecomment-2324945010

Link: https://bugs.passt.top/show_bug.cgi?id=95

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 udp.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/udp.c b/udp.c
index fe5df995..2ba00c9c 100644
--- a/udp.c
+++ b/udp.c
@@ -450,7 +450,8 @@ static int udp_sock_recverr(int s)
 static int udp_sock_errs(const struct ctx *c, int s, uint32_t events)
 {
 	unsigned n_err = 0;
-	int rc;
+	socklen_t errlen;
+	int rc, err;
 
 	ASSERT(!c->no_udp);
 
@@ -464,6 +465,24 @@ static int udp_sock_errs(const struct ctx *c, int s, uint32_t events)
 	if (rc < 0)
 		return -1; /* error reading error, unrecoverable */
 
+	errlen = sizeof(err);
+	if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0 ||
+	    errlen != sizeof(err)) {
+		err_perror("Error reading SO_ERROR");
+		return -1;  /* error reading error, unrecoverable */
+	}
+
+	if (err) {
+		debug("Unqueued error on UDP socket %i: %s", s, strerror(err));
+		n_err++;
+	}
+
+	if (!n_err) {
+		/* EPOLLERR, but no errors to clear !? */
+		err("EPOLLERR event without reported errors on socket %i", s);
+		return -1; /* no way to clear, unrecoverable */
+	}
+
 	return n_err;
 }
 
-- 
@@ -450,7 +450,8 @@ static int udp_sock_recverr(int s)
 static int udp_sock_errs(const struct ctx *c, int s, uint32_t events)
 {
 	unsigned n_err = 0;
-	int rc;
+	socklen_t errlen;
+	int rc, err;
 
 	ASSERT(!c->no_udp);
 
@@ -464,6 +465,24 @@ static int udp_sock_errs(const struct ctx *c, int s, uint32_t events)
 	if (rc < 0)
 		return -1; /* error reading error, unrecoverable */
 
+	errlen = sizeof(err);
+	if (getsockopt(s, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0 ||
+	    errlen != sizeof(err)) {
+		err_perror("Error reading SO_ERROR");
+		return -1;  /* error reading error, unrecoverable */
+	}
+
+	if (err) {
+		debug("Unqueued error on UDP socket %i: %s", s, strerror(err));
+		n_err++;
+	}
+
+	if (!n_err) {
+		/* EPOLLERR, but no errors to clear !? */
+		err("EPOLLERR event without reported errors on socket %i", s);
+		return -1; /* no way to clear, unrecoverable */
+	}
+
 	return n_err;
 }
 
-- 
2.46.0


  parent reply	other threads:[~2024-09-06  5:17 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-06  5:17 [PATCH 0/6] RFC: Possible fixes for bug 94 and bug 95 David Gibson
2024-09-06  5:17 ` [PATCH 1/6] flow: Fix incorrect hash probe in flowside_lookup() David Gibson
2024-09-06  5:17 ` [PATCH 2/6] udp: Allow UDP flows to be prematurely closed David Gibson
2024-09-06  5:17 ` [PATCH 3/6] flow: Helpers to log details of a flow David Gibson
2024-09-06  5:17 ` [PATCH 4/6] udp: Split socket error handling out from udp_sock_recv() David Gibson
2024-09-06  5:17 ` [PATCH 5/6] udp: Treat errors getting errors as unrecoverable David Gibson
2024-09-06  5:17 ` David Gibson [this message]
2024-09-06 11:29 ` [PATCH 0/6] RFC: Possible fixes for bug 94 and bug 95 Stefano Brivio

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240906051710.3863211-7-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).