From 03dce063f933a40d2f1e74503b99bc3768b0bf2d Mon Sep 17 00:00:00 2001 From: mutouyun Date: Sun, 6 Nov 2022 18:22:36 +0800 Subject: [PATCH] upd: [ipc] allow shm error codes to be passed out --- include/libimp/result.h | 32 +++++++------- src/libimp/platform/win/system.h | 8 ++-- src/libipc/platform/win/mmap_impl.h | 65 ++++++++++++++++------------- src/libipc/platform/win/shm_impl.h | 22 ++++++---- 4 files changed, 74 insertions(+), 53 deletions(-) diff --git a/include/libimp/result.h b/include/libimp/result.h index 5097282..d4c3bb2 100644 --- a/include/libimp/result.h +++ b/include/libimp/result.h @@ -17,23 +17,25 @@ LIBIMP_NAMESPACE_BEG_ +using result_type = std::uint64_t; + /** * @brief Use the least significant (in Little-Endian) of * a 64-bit unsigned integer to indicate success or failure, * so the data significant bit cannot exceed 63 bits. */ class LIBIMP_EXPORT result_code { - std::uint64_t status_; + result_type status_; public: result_code() noexcept; - result_code(std::uint64_t value) noexcept; - result_code(bool ok, std::uint64_t value) noexcept; + result_code(result_type value) noexcept; + result_code(bool ok, result_type value) noexcept; - std::uint64_t value() const noexcept; + result_type value() const noexcept; bool ok() const noexcept; - std::uint64_t operator*() const noexcept { + result_type operator*() const noexcept { return value(); } explicit operator bool() const noexcept { @@ -62,10 +64,10 @@ template struct default_traits::value>> { constexpr static T value() noexcept { return 0; } - static std::uint64_t cast_to_code(T value) noexcept { - return static_cast(value); + static result_type cast_to_code(T value) noexcept { + return static_cast(value); } - static T cast_from_code(std::uint64_t code) noexcept { + static T cast_from_code(result_type code) noexcept { return static_cast(code); } template @@ -78,10 +80,10 @@ template struct default_traits::value>> { constexpr static T value() noexcept { return nullptr; } - static std::uint64_t cast_to_code(T value) noexcept { - return reinterpret_cast(value); + static result_type cast_to_code(T value) noexcept { + return reinterpret_cast(value); } - static T cast_from_code(std::uint64_t code) noexcept { + static T cast_from_code(result_type code) noexcept { return reinterpret_cast(code); } template @@ -89,7 +91,7 @@ struct default_traits::value>> { if LIBIMP_LIKELY(r) { return format_to(out, "{}", static_cast(*r)); } - return format_to(out, "{}, code = {}", static_cast(*r), r.code()); + return format_to(out, "{}, code = {}", static_cast(*r), r.code_value()); } }; @@ -137,12 +139,12 @@ public: : code_(default_traits_t::value() != value, default_traits_t::cast_to_code(value)) {} - result(std::nullptr_t, std::uint64_t code) noexcept + result(std::nullptr_t, result_type code) noexcept : code_(false, code) {} T value() const noexcept { return code_.ok() ? default_traits_t::cast_from_code(code_.value()) : nullptr; } bool ok() const noexcept { return code_.ok(); } - std::uint64_t code() const noexcept { return code_.value(); } + result_type code_value() const noexcept { return code_.value(); } T operator*() const noexcept { return value(); @@ -171,7 +173,7 @@ struct fmt::formatter<::LIBIMP_::result> { template <> struct fmt::formatter<::LIBIMP_::result_code> - : formatter<::LIBIMP_::result> { + : formatter<::LIBIMP_::result<::LIBIMP_::result_type>> { template auto format(::LIBIMP_::result_code r, FormatContext &ctx) { return format_to(ctx.out(), "[{}, value = {}]", (r ? "succ" : "fail"), *r); diff --git a/src/libimp/platform/win/system.h b/src/libimp/platform/win/system.h index 9fac939..6ad86a6 100644 --- a/src/libimp/platform/win/system.h +++ b/src/libimp/platform/win/system.h @@ -25,7 +25,9 @@ namespace sys { */ result_code error_code() noexcept { auto err = ::GetLastError(); - if (err == ERROR_SUCCESS) return {true}; + if (err == ERROR_SUCCESS) { + return {ERROR_SUCCESS}; + } return {false, std::uint64_t(err)}; } @@ -82,7 +84,7 @@ std::string error_str(result_code code) noexcept { * https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsysteminfo * https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getnativesysteminfo */ -std::int64_t conf(info r) noexcept { +result conf(info r) noexcept { LIBIMP_LOG_(); switch (r) { case info::page_size: { @@ -92,7 +94,7 @@ std::int64_t conf(info r) noexcept { } default: log.error("invalid info = {}", enum_cast(r)); - return -1; + return {}; } } diff --git a/src/libipc/platform/win/mmap_impl.h b/src/libipc/platform/win/mmap_impl.h index 3b19952..8d0d4ba 100644 --- a/src/libipc/platform/win/mmap_impl.h +++ b/src/libipc/platform/win/mmap_impl.h @@ -33,15 +33,18 @@ namespace { * @brief Closes an open object handle. * @see https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle */ -void mmap_close(HANDLE h) { +result_code mmap_close(HANDLE h) { LIBIMP_LOG_(); if (h == NULL) { log.error("handle is null."); - return; + return {}; } if (!::CloseHandle(h)) { - log.error("CloseHandle fails. error = {}", sys::error()); + auto err = sys::error(); + log.error("CloseHandle({}) fails. error = {}", h, err); + return err.code(); } + return {ERROR_SUCCESS}; } /** @@ -57,35 +60,38 @@ void mmap_close(HANDLE h) { * * @return File mapping object HANDLE, NULL on error */ -HANDLE mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept { +result mmap_open(std::string const &file, std::size_t size, mode::type type) noexcept { LIBIMP_LOG_(); if (file.empty()) { log.error("file name is empty."); - return NULL; + return {}; } auto t_name = detail::to_tstring(file); if (t_name.empty()) { log.error("file name is empty. (TCHAR conversion failed)"); - return NULL; + return {}; } /// @brief Opens a named file mapping object. - auto try_open = [&]() -> HANDLE { + auto try_open = [&]() -> result { HANDLE h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, t_name.c_str()); if (h == NULL) { - log.error("OpenFileMapping fails. error = {}", sys::error()); + auto err = sys::error(); + log.error("OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, {}) fails. error = {}", file, err); + return {nullptr, err.value()}; } return h; }; /// @brief Creates or opens a named or unnamed file mapping object for a specified file. - auto try_create = [&]() -> HANDLE { + auto try_create = [&]() -> result { HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, detail::get_sa(), PAGE_READWRITE | SEC_COMMIT, /// @remark dwMaximumSizeHigh always 0 here. 0, static_cast(size), t_name.c_str()); if (h == NULL) { - log.error("CreateFileMapping fails. error = {}", sys::error()); - return NULL; + auto err = sys::error(); + log.error("CreateFileMapping(PAGE_READWRITE | SEC_COMMIT, {}, {}) fails. error = {}", size, file, err); + return {nullptr, err.value()}; } return h; }; @@ -99,15 +105,16 @@ HANDLE mmap_open(std::string const &file, std::size_t size, mode::type type) noe return try_open(); } else if (!(type & mode::create)) { log.error("mode type is invalid. type = {}", type); - return NULL; + return {}; } - HANDLE h = try_create(); + auto h = try_create(); + if (!h) return h; /// @remark If the object exists before the function call, the function returns a handle to the existing object /// (with its current size, not the specified size), and GetLastError returns ERROR_ALREADY_EXISTS. if ((type == mode::create) && (::GetLastError() == ERROR_ALREADY_EXISTS)) { - mmap_close(h); log.info("the file being created already exists. file = {}, type = {}", file, type); - return NULL; + mmap_close(*h); + return {}; } return h; } @@ -116,16 +123,17 @@ HANDLE mmap_open(std::string const &file, std::size_t size, mode::type type) noe * @brief Maps a view of a file mapping into the address space of a calling process. * @see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile */ -LPVOID mmap_memof(HANDLE h) { +result mmap_memof(HANDLE h) { LIBIMP_LOG_(); if (h == NULL) { log.error("handle is null."); - return NULL; + return {}; } LPVOID mem = ::MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, 0); - if (h == NULL) { - log.error("MapViewOfFile fails. error = {}", sys::error()); - return NULL; + if (mem == NULL) { + auto err = sys::error(); + log.error("MapViewOfFile({}, FILE_MAP_ALL_ACCESS) fails. error = {}", h, err); + return {nullptr, err.value()}; } return mem; } @@ -134,16 +142,17 @@ LPVOID mmap_memof(HANDLE h) { * @brief Retrieves the size about a range of pages in the virtual address space of the calling process. * @see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualquery */ -SIZE_T mmap_sizeof(LPCVOID mem) { +result mmap_sizeof(LPCVOID mem) { LIBIMP_LOG_(); if (mem == NULL) { log.error("memory pointer is null."); - return 0; + return {}; } MEMORY_BASIC_INFORMATION mem_info {}; if (::VirtualQuery(mem, &mem_info, sizeof(mem_info)) == 0) { - log.error("VirtualQuery fails. error = {}", sys::error()); - return 0; + auto err = sys::error(); + log.error("VirtualQuery({}) fails. error = {}", mem, err); + return {false, (SIZE_T)err.value()}; } return mem_info.RegionSize; } @@ -152,20 +161,20 @@ SIZE_T mmap_sizeof(LPCVOID mem) { * @brief Unmaps a mapped view of a file from the calling process's address space. * @see https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-unmapviewoffile */ -void mmap_release(HANDLE h, LPCVOID mem) { +result_code mmap_release(HANDLE h, LPCVOID mem) { LIBIMP_LOG_(); if (h == NULL) { log.error("handle is null."); - return; + return {}; } if (mem == NULL) { log.error("memory pointer is null."); - return; + return {}; } if (!::UnmapViewOfFile(mem)) { log.warning("UnmapViewOfFile fails. error = {}", sys::error()); } - mmap_close(h); + return mmap_close(h); } } // namespace diff --git a/src/libipc/platform/win/shm_impl.h b/src/libipc/platform/win/shm_impl.h index bda8d92..fa23f46 100644 --- a/src/libipc/platform/win/shm_impl.h +++ b/src/libipc/platform/win/shm_impl.h @@ -22,13 +22,21 @@ result shm_open(std::string name, std::size_t size, mode::type type) noex auto h = mmap_open(name, size, type); if (h == NULL) { log.error("mmap_open failed."); - return {nullptr, *sys::error_code()}; + return {nullptr, h.code_value()}; } - auto mem = mmap_memof(h); - if (mem == NULL) { - log.warning("mmap_memof failed."); + auto mem = mmap_memof(*h); + if (*mem == NULL) { + log.error("mmap_memof failed."); + mmap_close(*h); + return {nullptr, mem.code_value()}; } - return new shm_handle{std::move(name), mmap_sizeof(mem), mem, h}; + auto sz = mmap_sizeof(*mem); + if (!sz) { + log.error("mmap_sizeof failed."); + mmap_close(*h); + return {nullptr, static_cast(sz.value())}; + } + return new shm_handle{std::move(name), *sz, *mem, *h}; } result_code shm_close(shm_t h) noexcept { @@ -38,9 +46,9 @@ result_code shm_close(shm_t h) noexcept { return {}; } auto shm = static_cast(h); - mmap_release(shm->h_fmap, shm->memp); + auto ret = mmap_release(shm->h_fmap, shm->memp); delete shm; - return {0}; + return ret; } LIBIPC_NAMESPACE_END_