diff --git a/pvAccessApp/remote/blockingTCPConnector.cpp b/pvAccessApp/remote/blockingTCPConnector.cpp index a4cb358..6a4f8bb 100644 --- a/pvAccessApp/remote/blockingTCPConnector.cpp +++ b/pvAccessApp/remote/blockingTCPConnector.cpp @@ -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 diff --git a/pvAccessApp/remote/blockingTCPTransport.cpp b/pvAccessApp/remote/blockingTCPTransport.cpp index faa88e4..b666950 100644 --- a/pvAccessApp/remote/blockingTCPTransport.cpp +++ b/pvAccessApp/remote/blockingTCPTransport.cpp @@ -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: "<getPosition(), limit); diff --git a/pvAccessApp/remote/blockingUDPConnector.cpp b/pvAccessApp/remote/blockingUDPConnector.cpp index e784476..248295d 100644 --- a/pvAccessApp/remote/blockingUDPConnector.cpp +++ b/pvAccessApp/remote/blockingUDPConnector.cpp @@ -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(); } diff --git a/pvAccessApp/remote/blockingUDPTransport.cpp b/pvAccessApp/remote/blockingUDPTransport.cpp index 385cc82..3760392 100644 --- a/pvAccessApp/remote/blockingUDPTransport.cpp +++ b/pvAccessApp/remote/blockingUDPTransport.cpp @@ -25,7 +25,6 @@ #include #include #include -#include 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; }