aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/catman.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-02-08 14:50:53 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-02-08 14:50:53 +0000
commit05ede23b72a253dad7a9e6f68dc14d4f2a1ea3c2 (patch)
treeec891092b355edfad8f599aa3973c1c9d2608ddc /catman.c
parentb140f728b1a314f05c33e6804550714d3dd706d7 (diff)
downloadmandoc-05ede23b72a253dad7a9e6f68dc14d4f2a1ea3c2.tar.gz
mandoc-05ede23b72a253dad7a9e6f68dc14d4f2a1ea3c2.tar.zst
mandoc-05ede23b72a253dad7a9e6f68dc14d4f2a1ea3c2.zip
sendmsg(3) may block, so retry
Diffstat (limited to 'catman.c')
-rw-r--r--catman.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/catman.c b/catman.c
index 5ecef67e..6c9276d4 100644
--- a/catman.c
+++ b/catman.c
@@ -1,4 +1,4 @@
-/* $Id: catman.c,v 1.14 2017/02/06 19:02:37 schwarze Exp $ */
+/* $Id: catman.c,v 1.15 2017/02/08 14:50:53 schwarze Exp $ */
/*
* Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
* Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -34,6 +34,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
int process_manpage(int, int, const char *);
@@ -62,6 +63,7 @@ run_mandocd(int sockfd, const char *outtype, const char* defos)
ssize_t
sock_fd_write(int fd, int fd0, int fd1, int fd2)
{
+ const struct timespec timeout = { 0, 10000000 }; /* 0.01 s */
struct msghdr msg;
struct iovec iov;
union {
@@ -70,6 +72,7 @@ sock_fd_write(int fd, int fd0, int fd1, int fd2)
} cmsgu;
struct cmsghdr *cmsg;
int *walk;
+ ssize_t sz;
unsigned char dummy[1] = {'\0'};
iov.iov_base = dummy;
@@ -93,7 +96,21 @@ sock_fd_write(int fd, int fd0, int fd1, int fd2)
*(walk++) = fd1;
*(walk++) = fd2;
- return sendmsg(fd, &msg, 0);
+ /*
+ * It appears that on some systems, sendmsg(3)
+ * may return EAGAIN even in blocking mode.
+ * Seen for example on Oracle Solaris 11.2.
+ * The sleeping time was chosen by experimentation,
+ * to neither cause more than a handful of retries
+ * in normal operation nor unnecessary delays.
+ */
+ for (;;) {
+ if ((sz = sendmsg(fd, &msg, 0)) != -1 ||
+ errno != EAGAIN)
+ break;
+ nanosleep(&timeout, NULL);
+ }
+ return sz;
}
int