diff --git a/onnxruntime/core/platform/env.cc b/onnxruntime/core/platform/env.cc index 5ebda75b7c536..bb34e02e7c113 100644 --- a/onnxruntime/core/platform/env.cc +++ b/onnxruntime/core/platform/env.cc @@ -34,4 +34,29 @@ std::ostream& operator<<(std::ostream& os, gsl::span af Env::Env() = default; +std::pair GetErrnoInfo() { + auto err = errno; + std::string msg; + + if (err != 0) { + char buf[512]; + +#if defined(_WIN32) + auto ret = strerror_s(buf, sizeof(buf), err); + msg = ret == 0 ? buf : "Failed to get error message"; // buf is guaranteed to be null terminated by strerror_s +#else + // strerror_r return type differs by platform. + auto ret = strerror_r(err, buf, sizeof(buf)); + if constexpr (std::is_same_v) { // POSIX returns int + msg = ret == 0 ? buf : "Failed to get error message"; + } else { + // GNU returns char* + msg = ret; + } +#endif + } + + return {err, msg}; +} + } // namespace onnxruntime diff --git a/onnxruntime/core/platform/env.h b/onnxruntime/core/platform/env.h index 0425b2972f872..6917f42091bf3 100644 --- a/onnxruntime/core/platform/env.h +++ b/onnxruntime/core/platform/env.h @@ -96,6 +96,12 @@ struct ThreadOptions { std::ostream& operator<<(std::ostream& os, const LogicalProcessors&); std::ostream& operator<<(std::ostream& os, gsl::span); +/// +/// Get errno and the corresponding error message. +/// +/// errno and the error message string if errno indicates an error. +std::pair GetErrnoInfo(); + /// \brief An interface used by the onnxruntime implementation to /// access operating system functionality like the filesystem etc. /// diff --git a/onnxruntime/core/platform/posix/env.cc b/onnxruntime/core/platform/posix/env.cc index 7cd81d89d7d4d..9999550c241c8 100644 --- a/onnxruntime/core/platform/posix/env.cc +++ b/onnxruntime/core/platform/posix/env.cc @@ -62,39 +62,11 @@ class UnmapFileParam { size_t len; }; -/** - * @brief Get System Error - * - * @return a pair of {errno, error message} - */ -static std::pair GetSystemError(int e) { - char buf[1024]; - const char* msg = ""; - if (e > 0) { -#if defined(__GLIBC__) && defined(_GNU_SOURCE) && !defined(__ANDROID__) - msg = strerror_r(e, buf, sizeof(buf)); -#else - // for Mac OS X and Android lower than API 23 - if (strerror_r(e, buf, sizeof(buf)) != 0) { - buf[0] = '\0'; - } - msg = buf; -#endif - } - - return std::make_pair(e, msg); -} - -static std::pair GetSystemError() { - auto e = errno; - return GetSystemError(e); -} - static void UnmapFile(void* param) noexcept { std::unique_ptr p(reinterpret_cast(param)); int ret = munmap(p->addr, p->len); if (ret != 0) { - auto [err_no, err_msg] = GetSystemError(); + auto [err_no, err_msg] = GetErrnoInfo(); LOGS_DEFAULT(ERROR) << "munmap failed. error code: " << err_no << " error msg: " << err_msg; } } @@ -104,8 +76,9 @@ struct FileDescriptorTraits { static Handle GetInvalidHandleValue() { return -1; } static void CleanUp(Handle h) { if (close(h) == -1) { - auto [err_no, err_msg] = GetSystemError(); - LOGS_DEFAULT(ERROR) << "Failed to close file descriptor " << h << " - error code: " << err_no << " error msg: " << err_msg; + auto [err_no, err_msg] = GetErrnoInfo(); + LOGS_DEFAULT(ERROR) << "Failed to close file descriptor " << h << " - error code: " << err_no + << " error msg: " << err_msg; } } }; @@ -131,7 +104,7 @@ int nftw_remove( int /*typeflag*/, struct FTW* /*ftwbuf*/) { const auto result = remove(fpath); if (result != 0) { - auto [err_no, err_msg] = GetSystemError(); + auto [err_no, err_msg] = GetErrnoInfo(); LOGS_DEFAULT(WARNING) << "remove() failed. Error code: " << err_no << " error msg: " << err_msg << ", path: " << fpath; } @@ -188,7 +161,7 @@ class PosixThread : public EnvThread { pthread_attr_t attr; int s = pthread_attr_init(&attr); if (s != 0) { - auto [err_no, err_msg] = GetSystemError(); + auto [err_no, err_msg] = GetErrnoInfo(); ORT_THROW("pthread_attr_init failed, error code: ", err_no, " error msg: ", err_msg); } @@ -196,14 +169,14 @@ class PosixThread : public EnvThread { if (stack_size > 0) { s = pthread_attr_setstacksize(&attr, stack_size); if (s != 0) { - auto [err_no, err_msg] = GetSystemError(); + auto [err_no, err_msg] = GetErrnoInfo(); ORT_THROW("pthread_attr_setstacksize failed, error code: ", err_no, " error msg: ", err_msg); } } s = pthread_create(&hThread, &attr, ThreadMain, param_ptr.get()); if (s != 0) { - auto [err_no, err_msg] = GetSystemError(); + auto [err_no, err_msg] = GetErrnoInfo(); ORT_THROW("pthread_create failed, error code: ", err_no, " error msg: ", err_msg); } param_ptr.release(); @@ -249,7 +222,8 @@ class PosixThread : public EnvThread { << ", index: " << p->index << ", mask: " << *p->affinity; } else { - auto [err_no, err_msg] = GetSystemError(ret); + errno = ret; + auto [err_no, err_msg] = GetErrnoInfo(); #if !defined(USE_MIGRAPHX) LOGS_DEFAULT(ERROR) << "pthread_setaffinity_np failed for thread: " << syscall(SYS_gettid) << ", index: " << p->index @@ -461,7 +435,7 @@ class PosixEnv : public Env { } static common::Status ReportSystemError(const char* operation_name, const std::string& path) { - auto [err_no, err_msg] = GetSystemError(); + auto [err_no, err_msg] = GetErrnoInfo(); std::ostringstream oss; oss << operation_name << " file \"" << path << "\" failed: " << err_msg; return common::Status(common::SYSTEM, err_no, oss.str()); diff --git a/onnxruntime/core/platform/windows/env.cc b/onnxruntime/core/platform/windows/env.cc index 0b2db3f33f4b9..dc090e446e60f 100644 --- a/onnxruntime/core/platform/windows/env.cc +++ b/onnxruntime/core/platform/windows/env.cc @@ -110,11 +110,10 @@ class WindowsThread : public EnvThread { local_param.get(), 0, &threadID); if (th_handle == 0) { - auto err = errno; auto dos_error = _doserrno; - char message_buf[256]; - strerror_s(message_buf, sizeof(message_buf), err); - ORT_THROW("WindowThread:_beginthreadex failed with message: ", message_buf, " doserrno: ", dos_error); + auto [err, msg] = GetErrnoInfo(); + ORT_THROW("WindowThread:_beginthreadex failed with errno:", err, " message:", msg, + " doserrno:", dos_error); } local_param.release(); hThread.reset(reinterpret_cast(th_handle)); diff --git a/onnxruntime/test/platform/env_test.cc b/onnxruntime/test/platform/env_test.cc index e0bffed8c4c17..9ea8586af693b 100644 --- a/onnxruntime/test/platform/env_test.cc +++ b/onnxruntime/test/platform/env_test.cc @@ -33,5 +33,25 @@ TEST(PlatformEnvTest, DirectoryCreationAndDeletion) { ASSERT_FALSE(env.FolderExists(root_dir)); } +TEST(PlatformEnvTest, GetErrnoInfo) { + // command that should generate an errno error + std::ifstream file("non_existent_file"); + ASSERT_TRUE(file.fail()); + auto [err, msg] = GetErrnoInfo(); + ASSERT_EQ(err, ENOENT); + +#if defined(_WIN32) +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + + // GetErrnoInfo uses strerror_r or strerror_s depending on the platform. use the unsafe std::sterror to get the + // expected value given this is a unit test so doesn't have to be as robust. + ASSERT_EQ(msg, std::strerror(ENOENT)); + +#if defined(_WIN32) +#pragma warning(pop) +#endif +} } // namespace test } // namespace onnxruntime