socket spurious status checks

This commit is contained in:
Matej Sekoranja
2011-08-23 17:50:32 +02:00
parent fa21fc3bd5
commit dee09c353e
4 changed files with 95 additions and 26 deletions

View File

@@ -121,15 +121,22 @@ namespace epics {
int optval = 1; // true
int retval = ::setsockopt(socket, IPPROTO_TCP, TCP_NODELAY,
&optval, sizeof(int));
if(retval<0) errlogSevPrintf(errlogMajor,
"Error setting TCP_NODELAY: %s", strerror(errno));
if(retval<0) {
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Error setting TCP_NODELAY: %s", errStr);
}
// enable TCP_KEEPALIVE
retval = ::setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,
&optval, sizeof(int));
if(retval<0) errlogSevPrintf(errlogMinor,
"Error setting SO_KEEPALIVE: %s", strerror(errno));
if(retval<0)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMinor, "Error setting SO_KEEPALIVE: %s", errStr);
}
// TODO tune buffer sizes?! Win32 defaults are 8k, which is OK
// create transport

View File

@@ -131,17 +131,21 @@ namespace epics {
int retval = getsockopt(_channel, SOL_SOCKET, SO_SNDBUF, &_socketSendBufferSize, &intLen);
if(retval<0) {
_socketSendBufferSize = MAX_TCP_RECV;
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMinor,
"Unable to retrieve socket send buffer size: %s",
strerror(errno));
errStr);
}
socklen_t saSize = sizeof(sockaddr);
retval = getpeername(_channel, &(_socketAddress.sa), &saSize);
if(retval<0) {
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor,
"Error fetching socket remote address: %s",
strerror(errno));
errStr);
}
// prepare buffer
@@ -251,9 +255,13 @@ namespace epics {
int retval = getsockopt(_channel, SOL_SOCKET, SO_RCVBUF,&sockBufSize, &intLen);
if(retval<0)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor,
"Socket getsockopt SO_RCVBUF error: %s",
strerror(errno));
errStr);
}
return sockBufSize;
}
@@ -471,6 +479,11 @@ namespace epics {
_socketBuffer->put(readBuffer, 0, bytesRead);
if(bytesRead<=0) {
// spurious EINTR check
if (bytesRead<0 && SOCKERRNO==SOCK_EINTR)
continue;
// error (disconnect, end-of-stream) detected
close(true);
@@ -696,13 +709,34 @@ namespace epics {
if(bytesSent<0) {
int socketError = SOCKERRNO;
// spurious EINTR check
if (socketError==SOCK_EINTR)
continue;
// TODO check this (copy below)... consolidate!!!
if (socketError==SOCK_ENOBUFS) {
/* buffers full, reset the limit and indicate that there
* is more data to be sent
*/
if(bytesSent==maxBytesToSend) buffer->setLimit(limit);
return false;
}
// connection lost
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
ostringstream temp;
temp<<"error in sending TCP data: "<<strerror(errno);
temp<<"error in sending TCP data: "<<errStr;
//errlogSevPrintf(errlogMajor, "%s", temp.str().c_str());
THROW_BASE_EXCEPTION(temp.str().c_str());
}
else if(bytesSent==0) {
// TODO WINSOCK indicates disconnect by returning zero here !!!
//errlogSevPrintf(errlogInfo,
// "Buffer full, position %d of total %d bytes.",
// buffer->getPosition(), limit);

View File

@@ -41,7 +41,9 @@ namespace epics {
int retval = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
if(retval<0)
{
errlogSevPrintf(errlogMajor, "Error setting SO_BROADCAST: %s", strerror(errno));
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Error setting SO_BROADCAST: %s", errStr);
epicsSocketDestroy (socket);
return Transport::shared_pointer();
}
@@ -56,7 +58,9 @@ namespace epics {
retval = ::bind(socket, (sockaddr*)&(bindAddress.sa), sizeof(sockaddr));
if(retval<0) {
errlogSevPrintf(errlogMajor, "Error binding socket: %s", strerror(errno));
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Error binding socket: %s", errStr);
epicsSocketDestroy (socket);
return Transport::shared_pointer();
}

View File

@@ -25,7 +25,6 @@
#include <cstdio>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
using namespace epics::pvData;
using namespace std;
@@ -60,9 +59,11 @@ namespace epics {
if (setsockopt (_channel, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor,
"Failed to set SO_RCVTIMEO for UDP socket %s: %s.",
inetAddressToString(_bindAddress).c_str(), strerror(errno));
inetAddressToString(_bindAddress).c_str(), errStr);
}
@@ -105,6 +106,7 @@ namespace epics {
"UDP socket %s closed.",
inetAddressToString(_bindAddress).c_str());
// TODO should I wait thread to complete first and then destroy
epicsSocketDestroy(_channel);
}
@@ -214,14 +216,26 @@ namespace epics {
}
else if (bytesRead == -1) {
// timeout
if (errno == EAGAIN || errno == EWOULDBLOCK)
int socketError = SOCKERRNO;
// interrupted or timeout
if (socketError == EINTR ||
socketError == EAGAIN ||
socketError == EWOULDBLOCK)
continue;
if (socketError == SOCK_ECONNREFUSED || // avoid spurious ECONNREFUSED in Linux
socketError == SOCK_ECONNRESET) // or ECONNRESET in Windows
continue;
// log a 'recvfrom' error
if(!_closed)
errlogSevPrintf(errlogMajor, "Socket recv error: %s", strerror(errno));
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Socket recvfrom error: %s", errStr);
}
close(true, false);
break;
}
@@ -282,9 +296,11 @@ namespace epics {
buffer->flip();
int retval = sendto(_channel, buffer->getArray(),
buffer->getLimit(), 0, &(address.sa), sizeof(sockaddr));
if(retval<0) {
errlogSevPrintf(errlogMajor, "Socket sendto error: %s",
strerror(errno));
if(retval<0)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Socket sendto error: %s", errStr);
return false;
}
@@ -300,7 +316,12 @@ namespace epics {
buffer->getLimit(), 0, &(_sendAddresses->at(i).sa),
sizeof(sockaddr));
{
if(retval<0) errlogSevPrintf(errlogMajor, "Socket sendto error: %s", strerror(errno));
if(retval<0)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Socket sendto error: %s", errStr);
}
return false;
}
}
@@ -316,10 +337,13 @@ namespace epics {
int sockBufSize = -1;
socklen_t intLen = sizeof(int);
int retval = getsockopt(_channel, SOL_SOCKET, SO_RCVBUF,
&sockBufSize, &intLen);
if(retval<0) errlogSevPrintf(errlogMajor,
"Socket getsockopt SO_RCVBUF error: %s", strerror(errno));
int retval = getsockopt(_channel, SOL_SOCKET, SO_RCVBUF, &sockBufSize, &intLen);
if(retval<0)
{
char errStr[64];
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
errlogSevPrintf(errlogMajor, "Socket getsockopt SO_RCVBUF error: %s", errStr);
}
return sockBufSize;
}