socket spurious status checks
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user