diff --git a/lib/libknc.c b/lib/libknc.c index afc8d5a..41888fd 100644 --- a/lib/libknc.c +++ b/lib/libknc.c @@ -2248,8 +2248,20 @@ fdwritev(void *cookie, const struct iovec *iov, int iovcnt) { int fd = ((struct fd_cookie *)cookie)->wfd; -#ifdef O_NOSIGPIPE - return writev(fd, iov, iovcnt); +#if defined(O_NOSIGPIPE) || defined(MSG_NOSIGNAL) +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + struct msghdr msg = { 0 }; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = (void *)(uintptr_t)iov; + msg.msg_iovlen = iovcnt; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + return sendmsg(fd, &msg, MSG_NOSIGNAL); #else struct timespec ts_zero = {0, 0}; sigset_t blocked; @@ -2264,6 +2276,10 @@ fdwritev(void *cookie, const struct iovec *iov, int iovcnt) * outside our control. Basically, check to see if there's * one pending, if not block SIGPIPE, do the writev(2), * consume any generated SIGPIPE, and restore the old sigmask. + * + * pthread_sigmask() is thread-safe, but sigismember() and + * sigtimedwait() are not. We might end up consuming a SIGPIPE + * we shouldn't consume. */ sigemptyset(&blocked);