[PATCH] messaging: Fix queueing on FreeBSD

Volker Lendecke Volker.Lendecke at SerNet.DE
Tue Jun 20 14:55:48 UTC 2017


Hi!

Without this the local.messaging tests fail on FreeBSD, in particular
the overflow one.

Review appreciated!

Thanks, Volker

-- 
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 8f190bb68c96e20b569666861c35fbb291816c16 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 23 Nov 2016 16:51:25 +0100
Subject: [PATCH] messaging: Fix queueing on FreeBSD

FreeBSD does not do the nice blocking send that Linux does. Instead,
it returns ENOBUFS if the dst socket is full. According to the
manpage you have to do polling. Try with exponential backoff, at
the end try once a second forever.

Signed-off-by: Volker Lendecke <vl at samba.org>
---
 source3/lib/messages_dgm.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index 095a319..f29180d 100644
--- a/source3/lib/messages_dgm.c
+++ b/source3/lib/messages_dgm.c
@@ -541,9 +541,35 @@ static void messaging_dgm_out_threaded_job(void *private_data)
 	struct iovec iov = { .iov_base = state->buf,
 			     .iov_len = talloc_get_size(state->buf) };
 	size_t num_fds = talloc_array_length(state->fds);
+	int msec = 1;
 
-	state->sent = messaging_dgm_sendmsg(state->sock, &iov, 1,
+	while (true) {
+		int ret;
+
+		state->sent = messaging_dgm_sendmsg(state->sock, &iov, 1,
 					    state->fds, num_fds, &state->err);
+
+		if (state->sent != -1) {
+			return;
+		}
+		if (errno != ENOBUFS) {
+			return;
+		}
+
+		/*
+		 * ENOBUFS is the FreeBSD way of saying "Try
+		 * again". We have to do polling.
+		 */
+		do {
+			ret = poll(NULL, 0, msec);
+		} while ((ret == -1) && (errno == EINTR));
+
+		/*
+		 * Exponential backoff up to once a second
+		 */
+		msec *= 2;
+		msec = MIN(msec, 1000);
+	}
 }
 
 /*
@@ -619,6 +645,15 @@ static int messaging_dgm_out_send_fragment(
 			return 0;
 		}
 
+		if (err == ENOBUFS) {
+			/*
+			 * FreeBSD's way of telling us the dst socket
+			 * is full. EWOULDBLOCK makes us spawn a
+			 * polling helper thread.
+			 */
+			err = EWOULDBLOCK;
+		}
+
 		if (err != EWOULDBLOCK) {
 			return err;
 		}
-- 
2.1.4



More information about the samba-technical mailing list