summaryrefslogtreecommitdiff
path: root/source3/lib
diff options
context:
space:
mode:
authorVolker Lendecke <vl@samba.org>2016-11-23 16:51:25 +0100
committerJeremy Allison <jra@samba.org>2017-06-20 23:03:11 +0200
commitd7ccf0d977c39d49c29a4abb1d0b3e2f7a406016 (patch)
treef8ae8311ec4e0704dce4ff18318ada586a273fbd /source3/lib
parentb67262b40a924d5fa6576aacd2409ace808c730d (diff)
downloadsamba-d7ccf0d977c39d49c29a4abb1d0b3e2f7a406016.tar.gz
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@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org> Autobuild-User(master): Jeremy Allison <jra@samba.org> Autobuild-Date(master): Tue Jun 20 23:03:11 CEST 2017 on sn-devel-144
Diffstat (limited to 'source3/lib')
-rw-r--r--source3/lib/messages_dgm.c37
1 files changed, 36 insertions, 1 deletions
diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c
index 095a319f94a..f29180d7ec2 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;
}