krb5 commit: Prevent SIGPIPE from socket writes on UNIX-likes

Greg Hudson ghudson at mit.edu
Wed Oct 17 15:23:06 EDT 2018


https://github.com/krb5/krb5/commit/98bf22027bd6e746f456a671ca5e257ca4bd371e
commit 98bf22027bd6e746f456a671ca5e257ca4bd371e
Author: Robbie Harwood <rharwood at redhat.com>
Date:   Fri Oct 12 16:57:05 2018 -0400

    Prevent SIGPIPE from socket writes on UNIX-likes
    
    When writing to a disconnected socket, try to only get EPIPE rather
    than taking down the process with SIGPIPE.
    
    On recent Linux and other systems which have it, switch from writev to
    sendmsg and pass MSG_NOSIGNAL.
    
    On BSD-likes, set SO_NOSIGPIPE at connect time.
    
    ticket: 8753 (new)

 src/include/port-sockets.h |   43 ++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/src/include/port-sockets.h b/src/include/port-sockets.h
index f0fc2b8..57e5d1d 100644
--- a/src/include/port-sockets.h
+++ b/src/include/port-sockets.h
@@ -159,6 +159,7 @@ typedef int socklen_t;
 #include <netinet/in.h>         /* For struct sockaddr_in and in_addr */
 #include <arpa/inet.h>          /* For inet_ntoa */
 #include <netdb.h>
+#include <string.h>             /* For memset */
 
 #ifndef HAVE_NETDB_H_H_ERRNO
 extern int h_errno;             /* In case it's missing, e.g., HP-UX 10.20. */
@@ -219,15 +220,51 @@ typedef struct iovec sg_buf;
 #define SOCKET_NFDS(f)          ((f)+1) /* select() arg for a single fd */
 #define SOCKET_READ             read
 #define SOCKET_WRITE            write
-#define SOCKET_CONNECT          connect
+static inline int
+socket_connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
+{
+    int st;
+#ifdef SO_NOSIGPIPE
+    int set = 1;
+#endif
+
+    st = connect(fd, addr, addrlen);
+    if (st == -1)
+        return st;
+
+#ifdef SO_NOSIGPIPE
+    st = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
+    if (st != 0)
+        st = -1;
+#endif
+
+    return st;
+}
+#define SOCKET_CONNECT          socket_connect
 #define SOCKET_GETSOCKNAME      getsockname
 #define SOCKET_CLOSE            close
 #define SOCKET_EINTR            EINTR
 #define SOCKET_WRITEV_TEMP int
+static inline ssize_t
+socket_sendmsg(SOCKET fd, sg_buf *iov, int iovcnt)
+{
+    struct msghdr msg;
+    int flags = 0;
+
+#ifdef MSG_NOSIGNAL
+    flags |= MSG_NOSIGNAL;
+#endif
+
+    memset(&msg, 0, sizeof(msg));
+    msg.msg_iov = iov;
+    msg.msg_iovlen = iovcnt;
+
+    return sendmsg(fd, &msg, flags);
+}
 /* Use TMP to avoid compiler warnings and keep things consistent with
  * Windows version. */
-#define SOCKET_WRITEV(FD, SG, LEN, TMP)         \
-    ((TMP) = writev((FD), (SG), (LEN)), (TMP))
+#define SOCKET_WRITEV(FD, SG, LEN, TMP)                 \
+    ((TMP) = socket_sendmsg((FD), (SG), (LEN)), (TMP))
 
 #define SHUTDOWN_READ   0
 #define SHUTDOWN_WRITE  1


More information about the cvs-krb5 mailing list