THRIFT-96. cpp: TSocket.peek fails on FreeBSD
Author: Alexander Shigin
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@750585 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/transport/TSocket.cpp b/lib/cpp/src/transport/TSocket.cpp
index 04cd81e..1696053 100644
--- a/lib/cpp/src/transport/TSocket.cpp
+++ b/lib/cpp/src/transport/TSocket.cpp
@@ -96,6 +96,17 @@
int r = recv(socket_, &buf, 1, MSG_PEEK);
if (r == -1) {
int errno_copy = errno;
+ #ifdef __FreeBSD__
+ /* shigin:
+ * freebsd returns -1 and ECONNRESET if socket was closed by
+ * the other side
+ */
+ if (errno_copy == ECONNRESET)
+ {
+ close();
+ return false;
+ }
+ #endif
GlobalOutput.perror("TSocket::peek() recv() " + getSocketInfo(), errno_copy);
throw TTransportException(TTransportException::UNKNOWN, "recv()", errno_copy);
}
@@ -284,6 +295,7 @@
struct timeval begin;
gettimeofday(&begin, NULL);
int got = recv(socket_, buf, len, 0);
+ int errno_copy = errno; //gettimeofday can change errno
struct timeval end;
gettimeofday(&end, NULL);
uint32_t readElapsedMicros = (((end.tv_sec - begin.tv_sec) * 1000 * 1000)
@@ -292,7 +304,7 @@
// Check for error on read
if (got < 0) {
- if (errno == EAGAIN) {
+ if (errno_copy == EAGAIN) {
// check if this is the lack of resources or timeout case
if (!eagainThresholdMicros || (readElapsedMicros < eagainThresholdMicros)) {
if (retries++ < maxRecvRetries_) {
@@ -310,31 +322,37 @@
}
// If interrupted, try again
- if (errno == EINTR && retries++ < maxRecvRetries_) {
+ if (errno_copy == EINTR && retries++ < maxRecvRetries_) {
goto try_again;
}
// Now it's not a try again case, but a real probblez
- int errno_copy = errno; // Copy errno because we're allocating memory.
GlobalOutput.perror("TSocket::read() recv() " + getSocketInfo(), errno_copy);
// If we disconnect with no linger time
- if (errno == ECONNRESET) {
+ if (errno_copy == ECONNRESET) {
+ #ifdef __FreeBSD__
+ /* shigin: freebsd doesn't follow POSIX semantic of recv and fails with
+ * ECONNRESET if peer performed shutdown
+ */
+ close();
+ return 0;
+ #else
throw TTransportException(TTransportException::NOT_OPEN, "ECONNRESET");
+ #endif
}
// This ish isn't open
- if (errno == ENOTCONN) {
+ if (errno_copy == ENOTCONN) {
throw TTransportException(TTransportException::NOT_OPEN, "ENOTCONN");
}
// Timed out!
- if (errno == ETIMEDOUT) {
+ if (errno_copy == ETIMEDOUT) {
throw TTransportException(TTransportException::TIMED_OUT, "ETIMEDOUT");
}
// Some other error, whatevz
- errno_copy = errno;
throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy);
}