Porting MSG_MORE and MSG_NOSIGPIPE to OS X
I recently needed to port the following line of networking code in Ceph to OS X (Ceph is developed almost exclusively on Linux). The MSG_MORE flag is an optimization used to inform the networking layer that more data is going to be sent shortly. The MSG_NOSIGNAL flag is used to block SIGPIPE. Unfortunately both of these macros are not defined on OS X.
sendmsg(sd, msg, MSG_NOSIGNAL | (more ? MSG_MORE : 0));
First, since the MSG_MORE flag is an optimization, we can turn it off if it isn’t available (note that while reading about MSG_MORE, it seems that a solution based on TCP_CORK may be possible, but that is for another time).
#ifndef MSG_MORE
# define MSG_MORE 0
#endif
As for MSG_NOSIGNAL, luckily OS X has a mechanism for blocking SIGPIPE, but not nearly as convenient. First, we need to detect when MSG_NOSIGNAL is not defined, and provide a compatibility macro definition that won’t affect the bitmask flags.
#ifndef MSG_NOSIGNAL
# define MSG_NOSIGNAL 0
# ifdef SO_NOSIGPIPE
# define CEPH_USE_SO_NOSIGPIPE
# else
# error "Cannot block SIGPIPE!"
# endif
#endif
Finally, we can use the SO_NOSIGPIPE socket option to block SIGPIPE when MSG_NOSIGNAL is not defined. The socket option can be set right after the socket is initially opened.
#ifdef CEPH_USE_SO_NOSIGPIPE
int val = 1;
int r = setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&val, sizeof(val));
if (r) {
r = -errno;
ldout(msgr->cct,0) << "couldn't set SO_NOSIGPIPE: " << cpp_strerror(r) << dendl;
}
#endif