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
struct iovec iov = { .iov_base = state->buf,
.iov_len = talloc_get_size(state->buf) };
size_t num_fds = talloc_array_length(state->fds);
struct iovec iov = { .iov_base = state->buf,
.iov_len = talloc_get_size(state->buf) };
size_t num_fds = talloc_array_length(state->fds);
- 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);
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);
+ }
+ 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;
}
if (err != EWOULDBLOCK) {
return err;
}