Avoid SIGPIPE on OS X without MSG_NOSIGNAL

OS X does not have Linux-specific option MSG_NOSIGNAL.
SIGPIPE can be avoided on OS X by using sockopt SO_NOSIGPIPE.
Credits: https://noahdesu.github.io/2014/01/16/port-sendmsg.html
This commit is contained in:
theirix 2016-07-10 21:44:14 +03:00
parent 14acb6bbed
commit 66f2001c7b
5 changed files with 34 additions and 2 deletions

27
include/tcpdefines.h Normal file
View File

@ -0,0 +1,27 @@
#pragma once
/**
* No MSG_NOSIGNAL on OS X.
* Avoid SIGPIPE by using sockopt call.
*/
#ifdef MSG_NOSIGNAL
# define AMQP_CPP_MSG_NOSIGNAL MSG_NOSIGNAL
#else
# define AMQP_CPP_MSG_NOSIGNAL 0
# ifdef SO_NOSIGPIPE
# define AMQP_CPP_USE_SO_NOSIGPIPE
# else
# error "Cannot block SIGPIPE!"
# endif
#endif
#ifdef AMQP_CPP_USE_SO_NOSIGPIPE
/**
* Ignore SIGPIPE when there is no MSG_NOSIGNAL.
*/
inline void set_sockopt_nosigpipe(int socket)
{
int optval = 1;
setsockopt(socket, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
}
#endif

View File

@ -40,6 +40,7 @@
#include "../include/outbuffer.h"
#include "../include/watchable.h"
#include "../include/monitor.h"
#include "../include/tcpdefines.h"
// amqp types
#include "../include/field.h"

View File

@ -189,7 +189,7 @@ public:
if (_out) return _out.add(buffer, size);
// there is no buffer, send the data right away
auto result = ::send(_socket, buffer, size, MSG_NOSIGNAL);
auto result = ::send(_socket, buffer, size, AMQP_CPP_MSG_NOSIGNAL);
// number of bytes sent
size_t bytes = result < 0 ? 0 : result;

View File

@ -236,7 +236,7 @@ public:
header.msg_iovlen = index;
// send the data
auto result = sendmsg(socket, &header, MSG_NOSIGNAL);
auto result = sendmsg(socket, &header, AMQP_CPP_MSG_NOSIGNAL);
// skip on error, or when nothing was written
if (result <= 0) return total > 0 ? total : result;

View File

@ -120,6 +120,10 @@ private:
// set the option
setsockopt(_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
#ifdef AMQP_CPP_USE_SO_NOSIGPIPE
set_sockopt_nosigpipe(_socket);
#endif
}
}
catch (const std::runtime_error &error)