From a4f5e90d4d6a594716f5a19d92e3da2c402a9c3c Mon Sep 17 00:00:00 2001 From: Sunghyun Park Date: Wed, 13 Dec 2023 19:42:08 +0000 Subject: [PATCH 1/3] wip --- src/support/pipe.h | 53 ++++++++++++++++++++++++++++++++++++++++++-- src/support/socket.h | 8 +++---- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/support/pipe.h b/src/support/pipe.h index d869504dc4e9..ef6ad65348f1 100644 --- a/src/support/pipe.h +++ b/src/support/pipe.h @@ -40,6 +40,14 @@ namespace tvm { namespace support { +static int GetLastErrorCode() { +#ifdef _WIN32 + return WSAGetLastError(); +#else + return errno; +#endif + } + /*! \brief Platform independent pipe */ class Pipe : public dmlc::Stream { public: @@ -52,6 +60,43 @@ class Pipe : public dmlc::Stream { #endif /*! \brief destructor */ ~Pipe() { Flush(); } + + /*! + * \brief Call a function and retry if an EINTR error is encountered. + * + * Socket operations can return EINTR when the interrupt handler + * is registered by the execution environment(e.g. python). + * We should retry if there is no KeyboardInterrupt recorded in + * the environment. + * + * \note This function is needed to avoid rare interrupt event + * in long running server code. + * + * \param func The function to retry. + * \return The return code returned by function f or error_value on retry failure. + */ + template + ssize_t RetryCallOnEINTR(FuncType func) { + ssize_t ret = func(); + // common path + if (ret != -1) return ret; + // less common path + do { + if (GetLastErrorCode() == EINTR) { + // Call into env check signals to see if there are + // environment specific(e.g. python) signal exceptions. + // This function will throw an exception if there is + // if the process received a signal that requires TVM to return immediately (e.g. SIGINT). + runtime::EnvCheckSignals(); + } else { + // other errors + return ret; + } + ret = func(); + } while (ret == -1); + return ret; + } + using Stream::Read; using Stream::Write; /*! @@ -68,7 +113,10 @@ class Pipe : public dmlc::Stream { << "Read Error: " << GetLastError(); #else ssize_t nread; - nread = read(handle_, ptr, size); + //nread = read(handle_, ptr, size); + + nread = RetryCallOnEINTR( + [&]() { return read(handle_, ptr, size); }); ICHECK_GE(nread, 0) << "Write Error: " << strerror(errno); #endif return static_cast(nread); @@ -88,7 +136,8 @@ class Pipe : public dmlc::Stream { << "Write Error: " << GetLastError(); #else ssize_t nwrite; - nwrite = write(handle_, ptr, size); + nwrite = RetryCallOnEINTR( + [&]() { return write(handle_, ptr, size); }); ICHECK_EQ(static_cast(nwrite), size) << "Write Error: " << strerror(errno); #endif } diff --git a/src/support/socket.h b/src/support/socket.h index f62702bbc445..009df42e6d2e 100644 --- a/src/support/socket.h +++ b/src/support/socket.h @@ -310,7 +310,7 @@ class Socket { /*! * \return last error of socket operation */ - static int GetLastError() { + static int GetLastErrorCode() { #ifdef _WIN32 return WSAGetLastError(); #else @@ -319,7 +319,7 @@ class Socket { } /*! \return whether last error was would block */ static bool LastErrorWouldBlock() { - int errsv = GetLastError(); + int errsv = GetLastErrorCode(); #ifdef _WIN32 return errsv == WSAEWOULDBLOCK; #else @@ -355,7 +355,7 @@ class Socket { * \param msg The error message. */ static void Error(const char* msg) { - int errsv = GetLastError(); + int errsv = GetLastErrorCode(); #ifdef _WIN32 LOG(FATAL) << "Socket " << msg << " Error:WSAError-code=" << errsv; #else @@ -384,7 +384,7 @@ class Socket { if (ret != -1) return ret; // less common path do { - if (GetLastError() == EINTR) { + if (GetLastErrorCode() == EINTR) { // Call into env check signals to see if there are // environment specific(e.g. python) signal exceptions. // This function will throw an exception if there is From b5e1d018930b3df3c1ac42fd7fa8b92648a194c0 Mon Sep 17 00:00:00 2001 From: Sunghyun Park Date: Wed, 13 Dec 2023 21:03:37 +0000 Subject: [PATCH 2/3] done --- src/support/err_handling.h | 77 ++++++++++++++++++++++++++++++++++++++ src/support/pipe.h | 45 +--------------------- src/support/socket.h | 49 +----------------------- 3 files changed, 80 insertions(+), 91 deletions(-) create mode 100644 src/support/err_handling.h diff --git a/src/support/err_handling.h b/src/support/err_handling.h new file mode 100644 index 000000000000..46b089cccbc6 --- /dev/null +++ b/src/support/err_handling.h @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/*! + * \file err_handling.h + * \brief Common error handling functions for socket.h and pipe.h + */ +#ifndef TVM_SUPPORT_ERR_HANDLING_H_ +#define TVM_SUPPORT_ERR_HANDLING_H_ +#include + +namespace tvm { +namespace support { + /*! + * \return last error of socket operation + */ + static int GetLastErrorCode() { +#ifdef _WIN32 + return WSAGetLastError(); +#else + return errno; +#endif + } + /*! + * \brief Call a function and retry if an EINTR error is encountered. + * + * Socket operations can return EINTR when the interrupt handler + * is registered by the execution environment(e.g. python). + * We should retry if there is no KeyboardInterrupt recorded in + * the environment. + * + * \note This function is needed to avoid rare interrupt event + * in long running server code. + * + * \param func The function to retry. + * \return The return code returned by function f or error_value on retry failure. + */ + template + inline ssize_t RetryCallOnEINTR(FuncType func) { + ssize_t ret = func(); + // common path + if (ret != -1) return ret; + // less common path + do { + if (GetLastErrorCode() == EINTR) { + // Call into env check signals to see if there are + // environment specific(e.g. python) signal exceptions. + // This function will throw an exception if there is + // if the process received a signal that requires TVM to return immediately (e.g. SIGINT). + runtime::EnvCheckSignals(); + } else { + // other errors + return ret; + } + ret = func(); + } while (ret == -1); + return ret; + } +} // namespace support +} // namespace tvm +#endif // TVM_SUPPORT_ERR_HANDLING_H_ diff --git a/src/support/pipe.h b/src/support/pipe.h index ef6ad65348f1..f35cdab55fbe 100644 --- a/src/support/pipe.h +++ b/src/support/pipe.h @@ -36,18 +36,11 @@ #include #include #endif +#include "../support/err_handling.h" namespace tvm { namespace support { -static int GetLastErrorCode() { -#ifdef _WIN32 - return WSAGetLastError(); -#else - return errno; -#endif - } - /*! \brief Platform independent pipe */ class Pipe : public dmlc::Stream { public: @@ -61,42 +54,6 @@ class Pipe : public dmlc::Stream { /*! \brief destructor */ ~Pipe() { Flush(); } - /*! - * \brief Call a function and retry if an EINTR error is encountered. - * - * Socket operations can return EINTR when the interrupt handler - * is registered by the execution environment(e.g. python). - * We should retry if there is no KeyboardInterrupt recorded in - * the environment. - * - * \note This function is needed to avoid rare interrupt event - * in long running server code. - * - * \param func The function to retry. - * \return The return code returned by function f or error_value on retry failure. - */ - template - ssize_t RetryCallOnEINTR(FuncType func) { - ssize_t ret = func(); - // common path - if (ret != -1) return ret; - // less common path - do { - if (GetLastErrorCode() == EINTR) { - // Call into env check signals to see if there are - // environment specific(e.g. python) signal exceptions. - // This function will throw an exception if there is - // if the process received a signal that requires TVM to return immediately (e.g. SIGINT). - runtime::EnvCheckSignals(); - } else { - // other errors - return ret; - } - ret = func(); - } while (ret == -1); - return ret; - } - using Stream::Read; using Stream::Write; /*! diff --git a/src/support/socket.h b/src/support/socket.h index 009df42e6d2e..a348c8b73332 100644 --- a/src/support/socket.h +++ b/src/support/socket.h @@ -39,7 +39,6 @@ #endif #else #include -#include #include #include #include @@ -58,6 +57,7 @@ #include "../support/ssize.h" #include "../support/utils.h" +#include "../support/err_handling.h" #if defined(_WIN32) static inline int poll(struct pollfd* pfd, int nfds, int timeout) { @@ -307,16 +307,7 @@ class Socket { Error("Socket::Close double close the socket or close without create"); } } - /*! - * \return last error of socket operation - */ - static int GetLastErrorCode() { -#ifdef _WIN32 - return WSAGetLastError(); -#else - return errno; -#endif - } + /*! \return whether last error was would block */ static bool LastErrorWouldBlock() { int errsv = GetLastErrorCode(); @@ -363,42 +354,6 @@ class Socket { #endif } - /*! - * \brief Call a function and retry if an EINTR error is encountered. - * - * Socket operations can return EINTR when the interrupt handler - * is registered by the execution environment(e.g. python). - * We should retry if there is no KeyboardInterrupt recorded in - * the environment. - * - * \note This function is needed to avoid rare interrupt event - * in long running server code. - * - * \param func The function to retry. - * \return The return code returned by function f or error_value on retry failure. - */ - template - ssize_t RetryCallOnEINTR(FuncType func) { - ssize_t ret = func(); - // common path - if (ret != -1) return ret; - // less common path - do { - if (GetLastErrorCode() == EINTR) { - // Call into env check signals to see if there are - // environment specific(e.g. python) signal exceptions. - // This function will throw an exception if there is - // if the process received a signal that requires TVM to return immediately (e.g. SIGINT). - runtime::EnvCheckSignals(); - } else { - // other errors - return ret; - } - ret = func(); - } while (ret == -1); - return ret; - } - protected: explicit Socket(SockType sockfd) : sockfd(sockfd) {} }; From 1e32a4b35b3571af73bdff39b9ebbe5a1e536a13 Mon Sep 17 00:00:00 2001 From: Sunghyun Park Date: Wed, 13 Dec 2023 21:15:24 +0000 Subject: [PATCH 3/3] done --- src/support/{err_handling.h => error_handling.h} | 0 src/support/pipe.h | 10 +++------- src/support/socket.h | 6 +++--- 3 files changed, 6 insertions(+), 10 deletions(-) rename src/support/{err_handling.h => error_handling.h} (100%) diff --git a/src/support/err_handling.h b/src/support/error_handling.h similarity index 100% rename from src/support/err_handling.h rename to src/support/error_handling.h diff --git a/src/support/pipe.h b/src/support/pipe.h index f35cdab55fbe..098b327625b9 100644 --- a/src/support/pipe.h +++ b/src/support/pipe.h @@ -36,7 +36,7 @@ #include #include #endif -#include "../support/err_handling.h" +#include "error_handling.h" namespace tvm { namespace support { @@ -69,10 +69,7 @@ class Pipe : public dmlc::Stream { ICHECK(ReadFile(handle_, static_cast(ptr), size, &nread, nullptr)) << "Read Error: " << GetLastError(); #else - ssize_t nread; - //nread = read(handle_, ptr, size); - - nread = RetryCallOnEINTR( + ssize_t nread = RetryCallOnEINTR( [&]() { return read(handle_, ptr, size); }); ICHECK_GE(nread, 0) << "Write Error: " << strerror(errno); #endif @@ -92,8 +89,7 @@ class Pipe : public dmlc::Stream { static_cast(nwrite) == size) << "Write Error: " << GetLastError(); #else - ssize_t nwrite; - nwrite = RetryCallOnEINTR( + ssize_t nwrite = RetryCallOnEINTR( [&]() { return write(handle_, ptr, size); }); ICHECK_EQ(static_cast(nwrite), size) << "Write Error: " << strerror(errno); #endif diff --git a/src/support/socket.h b/src/support/socket.h index a348c8b73332..9a645db83e75 100644 --- a/src/support/socket.h +++ b/src/support/socket.h @@ -55,9 +55,9 @@ #include #include -#include "../support/ssize.h" -#include "../support/utils.h" -#include "../support/err_handling.h" +#include "ssize.h" +#include "utils.h" +#include "error_handling.h" #if defined(_WIN32) static inline int poll(struct pollfd* pfd, int nfds, int timeout) {