From d5dffb70be8279d3ef24fd1d7ad924c97c968185 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 3 Apr 2020 12:19:25 +0200 Subject: [PATCH] Avoid generating the SIGPIPE signal Handling the SIGPIPE signal in a library is tricky, because installing a signal handler does affects the entire application. But we can at least try to avoid generating the SIGPIPE signal ourselves. On Linux, that requires the use of the MSG_NOSIGNAL flag, and on Mac and BSD setting the SO_NOSIGPIPE socket option. --- src/socket.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/socket.c b/src/socket.c index e9412ab..84d58a4 100644 --- a/src/socket.c +++ b/src/socket.c @@ -24,6 +24,10 @@ #include "common-private.h" #include "context-private.h" +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + dc_status_t dc_socket_syserror (s_errcode_t errcode) { @@ -106,8 +110,22 @@ dc_socket_open (dc_iostream_t *abstract, int family, int type, int protocol) goto error; } +#ifdef SO_NOSIGPIPE + int optval = 1; + if (setsockopt(device->fd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) != 0) { + s_errcode_t errcode = S_ERRNO; + SYSERROR (abstract->context, errcode); + status = dc_socket_syserror(errcode); + goto error_close; + } +#endif + return DC_STATUS_SUCCESS; +#ifdef SO_NOSIGPIPE +error_close: + S_CLOSE (device->fd); +#endif error: dc_socket_exit (abstract->context); return status; @@ -304,7 +322,7 @@ dc_socket_write (dc_iostream_t *abstract, const void *data, size_t size, size_t break; // Timeout. } - s_ssize_t n = send (socket->fd, (const char *) data + nbytes, size - nbytes, 0); + s_ssize_t n = send (socket->fd, (const char *) data + nbytes, size - nbytes, MSG_NOSIGNAL); if (n < 0) { s_errcode_t errcode = S_ERRNO; if (errcode == S_EINTR || errcode == S_EAGAIN)