=================================================================== RCS file: /cvs/mandoc/catman.c,v retrieving revision 1.14 retrieving revision 1.22 diff -u -p -r1.14 -r1.22 --- mandoc/catman.c 2017/02/06 19:02:37 1.14 +++ mandoc/catman.c 2020/06/14 23:40:31 1.22 @@ -1,4 +1,4 @@ -/* $Id: catman.c,v 1.14 2017/02/06 19:02:37 schwarze Exp $ */ +/* $Id: catman.c,v 1.22 2020/06/14 23:40:31 schwarze Exp $ */ /* * Copyright (c) 2017 Michael Stapelberg * Copyright (c) 2017 Ingo Schwarze @@ -17,6 +17,10 @@ */ #include "config.h" +#if NEED_XPG4_2 +#define _XPG4_2 +#endif + #include #include #include @@ -34,14 +38,15 @@ #include #include #include +#include #include int process_manpage(int, int, const char *); int process_tree(int, int); void run_mandocd(int, const char *, const char *) - __attribute__((noreturn)); + __attribute__((__noreturn__)); ssize_t sock_fd_write(int, int, int, int); -void usage(void) __attribute__((noreturn)); +void usage(void) __attribute__((__noreturn__)); void @@ -52,16 +57,18 @@ run_mandocd(int sockfd, const char *outtype, const cha if (snprintf(sockfdstr, sizeof(sockfdstr), "%d", sockfd) == -1) err(1, "snprintf"); if (defos == NULL) - execlp("mandocd", "mandocd", "-T", outtype, sockfdstr, NULL); + execlp("mandocd", "mandocd", "-T", outtype, + sockfdstr, (char *)NULL); else execlp("mandocd", "mandocd", "-T", outtype, - "-I", defos, sockfdstr, NULL); + "-I", defos, sockfdstr, (char *)NULL); err(1, "exec"); } 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 +77,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 +101,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 @@ -232,7 +254,7 @@ main(int argc, char **argv) void usage(void) { - fprintf(stderr, "usage: catman [-I os=name] [-T output] " - "srcdir dstdir\n"); + fprintf(stderr, "usage: %s [-I os=name] [-T output] " + "srcdir dstdir\n", BINM_CATMAN); exit(1); }