From 4f61786b711a0db9f52c1e7ad29094e2af847cc5 Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Wed, 4 Dec 2013 16:50:03 +0100 Subject: [PATCH] sstream.cpp: do a better job at handling the EINTR signal in recv() and send() --- include/mitsuba/core/sstream.h | 2 +- src/libcore/sstream.cpp | 24 +++++++++++++++++------- src/mtsgui/server.h | 1 + 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/include/mitsuba/core/sstream.h b/include/mitsuba/core/sstream.h index ea5161eb..a45fd94d 100644 --- a/include/mitsuba/core/sstream.h +++ b/include/mitsuba/core/sstream.h @@ -78,7 +78,7 @@ public: std::string toString() const; /// Handle the last socket-specific error (looks up the appropriate OS description) - static void handleError(const std::string &cmd, ELogLevel level = EError); + static bool handleError(const std::string &cmd, ELogLevel level = EError); //! @} // ============================================================= diff --git a/src/libcore/sstream.cpp b/src/libcore/sstream.cpp index 05729d11..676c0640 100644 --- a/src/libcore/sstream.cpp +++ b/src/libcore/sstream.cpp @@ -169,10 +169,12 @@ void SocketStream::read(void *ptr, size_t size) { if (n == 0) { throw EOFException("Connection closed while reading!", (size_t) (data - (char *) ptr)); - } else if (n == -1) { - handleError("recv", EWarn); + } else if (n == SOCKET_ERROR) { + if (!handleError("recv", EWarn)) + continue; /* Wasn't an error after all -- continue */ + throw EOFException("Connection closed while reading!", - (size_t) (data - (char *) ptr)); + (size_t) (data - (char *) ptr)); } size -= n; data += n; @@ -194,7 +196,9 @@ void SocketStream::write(const void *ptr, size_t size) { int n = send(m_socket, data, size, 0); #endif if (n == SOCKET_ERROR) { - handleError("send", EWarn); + if (!handleError("send", EWarn)) + continue; /* Wasn't an error after all -- continue */ + throw EOFException("Connection closed while writing!", (size_t) (data - (char *) ptr)); } @@ -242,7 +246,7 @@ void SocketStream::flush() { /* Ignore */ } -void SocketStream::handleError(const std::string &cmd, ELogLevel level) { +bool SocketStream::handleError(const std::string &cmd, ELogLevel level) { #ifndef WIN32 if (cmd.find("(") == std::string::npos) Log(level, "Error in %s(): %s!", cmd.c_str(), strerror(errno)); @@ -252,8 +256,13 @@ void SocketStream::handleError(const std::string &cmd, ELogLevel level) { std::string err; int error = WSAGetLastError(); switch (error) { - case WSABASEERR: err = "No Error"; break; - case WSAEINTR: err = "Interrupted system call"; break; + case WSABASEERR: err = "Internal error (no reason given)"; break; + case WSAEINTR: + if (level == EWarn) /* This is not really a warning -- just retry the operation. */ + return false; + else + err = "Interrupted system call"; + break; case WSAEBADF: err = "Bad file number"; break; case WSAEACCES: err = "Permission denied"; break; case WSAEFAULT: err = "Bad address"; break; @@ -309,6 +318,7 @@ void SocketStream::handleError(const std::string &cmd, ELogLevel level) { else Log(level, "Error %i in %s: %s!", error, cmd.c_str(), err.c_str()); #endif + return true; } MTS_IMPLEMENT_CLASS(SocketStream, false, Stream) diff --git a/src/mtsgui/server.h b/src/mtsgui/server.h index 328deb7a..69c86910 100644 --- a/src/mtsgui/server.h +++ b/src/mtsgui/server.h @@ -34,6 +34,7 @@ #include #include #include + #define INVALID_SOCKET -1 #define SOCKET int #endif