Files
fail/src/core/comm/SocketComm.cc
Horst Schirmeier 880e7a81ff comm: ignore SIGPIPE
This prevents client and server from being sent a SIGPIPE (and
terminating) when the other side unexpectedly closes the connection.
It's way easier to handle this condition when checking the write()
return value, than to do anything smart in a SIGPIPE handler.  More
details:
<http://stackoverflow.com/questions/108183/how-to-prevent-sigpipes-or-handle-them-properly>

Change-Id: I1da5bf5ef79c8b7b00ede976e96ed4f1c560049d
2013-04-29 15:32:12 +02:00

97 lines
2.0 KiB
C++

#include <string>
#include <errno.h>
#include <signal.h>
#include "SocketComm.hpp"
namespace fail {
void SocketComm::init()
{
// It's usually much easier to handle the error on write(), than to do
// anything intelligent in a SIGPIPE handler.
signal(SIGPIPE, SIG_IGN);
}
bool SocketComm::sendMsg(int sockfd, google::protobuf::Message& msg)
{
#ifdef USE_SIZE_PREFIX
int size = htonl(msg.ByteSize());
std::string buf;
if (safe_write(sockfd, &size, sizeof(size)) == -1
|| !msg.SerializeToString(&buf)
|| safe_write(sockfd, buf.c_str(), buf.size()) == -1) {
return false;
}
#else
char c = 0;
if (!msg.SerializeToFileDescriptor(sockfd)
|| safe_write(sockfd, &c, 1) == -1) {
return false;
}
#endif
return true;
}
bool SocketComm::rcvMsg(int sockfd, google::protobuf::Message& msg)
{
#ifdef USE_SIZE_PREFIX
int size;
if (safe_read(sockfd, &size, sizeof(size)) == -1) {
return false;
}
size = ntohl(size);
char *buf = new char[size];
if (safe_read(sockfd, buf, size) == -1) {
delete [] buf;
return false;
}
std::string st(buf, size);
delete [] buf;
return msg.ParseFromString(st);
#else
return msg.ParseFromFileDescriptor(sockfd);
#endif
}
ssize_t SocketComm::safe_write(int fd, const void *buf, size_t count)
{
ssize_t ret;
const char *cbuf = (const char *) buf;
do {
ret = write(fd, cbuf, count);
if (ret == -1) {
if (errno == EINTR) {
continue;
}
return -1;
}
count -= ret;
cbuf += ret;
} while (count);
return cbuf - (const char *)buf;
}
ssize_t SocketComm::safe_read(int fd, void *buf, size_t count)
{
ssize_t ret;
char *cbuf = (char *) buf;
do {
ret = read(fd, cbuf, count);
if (ret == -1) {
if (errno == EINTR) {
continue;
}
return -1;
} else if (ret == 0) {
// this deliberately deviates from read(2)
return -1;
}
count -= ret;
cbuf += ret;
} while (count);
return cbuf - (const char *) buf;
}
} // end-of-namespace: fail