diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index d97a56a34a..0741687007 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -108,7 +108,7 @@ jobs: # we have to exclude the tests explicitly until everyone is running - name: Run tests, excluding timing_tests run: | - build\hoofs\test\Debug\hoofs_moduletests.exe --gtest_filter="-*TimingTest*:IpcChannel*:Mutex*:UnixDomainSocket*" + build\hoofs\test\Debug\hoofs_moduletests.exe --gtest_filter="-*TimingTest*:UnixDomainSocket*" build\hoofs\test\Debug\hoofs_integrationtests.exe build\binding_c\test\Debug\binding_c_moduletests.exe --gtest_filter="-BindingC_Runtime*:*TimingTest*" build\posh\test\Debug\posh_moduletests.exe --gtest_filter="-PoshRuntime*:IceoryxRoudiApp*:IceoryxRoudiMemoryManager*:ProcessIntrospection*:ParseAllMalformedInput*:*TimingTest*" diff --git a/iceoryx_hoofs/include/iceoryx_hoofs/internal/posix_wrapper/shared_memory_object.hpp b/iceoryx_hoofs/include/iceoryx_hoofs/internal/posix_wrapper/shared_memory_object.hpp index 6a520c9c24..217a037190 100644 --- a/iceoryx_hoofs/include/iceoryx_hoofs/internal/posix_wrapper/shared_memory_object.hpp +++ b/iceoryx_hoofs/include/iceoryx_hoofs/internal/posix_wrapper/shared_memory_object.hpp @@ -64,7 +64,7 @@ class SharedMemoryObject : public DesignPattern::Creation { public: - static constexpr uint64_t NAME_SIZE = 128U; + static constexpr uint64_t NAME_SIZE = platform::IOX_MAX_SHM_NAME_LENGTH; + static constexpr int INVALID_HANDLE = -1; using Name_t = cxx::string; SharedMemory(const SharedMemory&) = delete; @@ -75,29 +88,50 @@ class SharedMemory : public DesignPattern::Creation unlinkIfExist(const Name_t& name) noexcept; + friend class DesignPattern::Creation; private: + /// @brief constructs or opens existing shared memory + /// @param[in] name the name of the shared memory, must start with a leading / + /// @param[in] accessMode defines if the shared memory is mapped read only or with read write rights + /// @param[in] openMode states how the shared memory is created/opened + /// @param[in] permissions the permissions the shared memory should have + /// @param[in] size the size in bytes of the shared memory SharedMemory(const Name_t& name, const AccessMode accessMode, - const OwnerShip ownerShip, + const OpenMode openMode, const mode_t permissions, const uint64_t size) noexcept; - bool open(const int oflags, const mode_t permissions, const uint64_t size) noexcept; + bool + open(const AccessMode accessMode, const OpenMode openMode, const mode_t permissions, const uint64_t size) noexcept; bool unlink() noexcept; bool close() noexcept; void destroy() noexcept; void reset() noexcept; + static int getOflagsFor(const AccessMode accessMode, const OpenMode openMode) noexcept; - SharedMemoryError errnoToEnum(const int32_t errnum) const noexcept; - + static SharedMemoryError errnoToEnum(const int32_t errnum) noexcept; Name_t m_name; - OwnerShip m_ownerShip; - int m_handle{-1}; + int m_handle{INVALID_HANDLE}; + bool m_hasOwnership{false}; }; } // namespace posix } // namespace iox diff --git a/iceoryx_hoofs/include/iceoryx_hoofs/posix_wrapper/file_lock.hpp b/iceoryx_hoofs/include/iceoryx_hoofs/posix_wrapper/file_lock.hpp index 3c1353217d..53d6bf37cc 100644 --- a/iceoryx_hoofs/include/iceoryx_hoofs/posix_wrapper/file_lock.hpp +++ b/iceoryx_hoofs/include/iceoryx_hoofs/posix_wrapper/file_lock.hpp @@ -27,10 +27,9 @@ namespace posix enum class FileLockError { INVALID_STATE, - NO_FILE_NAME_PROVIDED, + INVALID_FILE_NAME, LOCKED_BY_OTHER_PROCESS, ACCESS_DENIED, - INVALID_FILE_NAME, QUOTA_EXHAUSTED, INVALID_CHARACTERS_IN_FILE_NAME, SYSTEM_LIMIT, @@ -45,14 +44,6 @@ enum class FileLockError INTERNAL_LOGIC_ERROR, }; - -#if defined(QNX) || defined(QNX__) || defined(__QNX__) -constexpr char PATH_PREFIX[] = "/var/lock/"; -#else -constexpr char PATH_PREFIX[] = "/tmp/"; -#endif - - /// @brief Posix file lock C++ wrapping class /// Following RAII, the lock is acquired on creation and released on destruction. Releasing the locks works even /// if the process crashes with a segfault or using SIGKILL. 'lslocks' can be used to display all system-wide @@ -72,8 +63,13 @@ class FileLock : public DesignPattern::Creation public: static constexpr int32_t ERROR_CODE = -1; static constexpr int32_t INVALID_FD = -1; - using FileName_t = cxx::string<250>; - using PathName_t = cxx::string<1024>; + static constexpr const char LOCK_FILE_SUFFIX[] = ".lock"; + static constexpr uint64_t FILENAME_LENGTH = platform::IOX_MAX_FILENAME_LENGTH + - sizeof(platform::IOX_LOCK_FILE_PATH_PREFIX) / sizeof(char) + - sizeof(LOCK_FILE_SUFFIX) / sizeof(char); + + using FileName_t = cxx::string; + using PathName_t = cxx::string; FileLock(const FileLock&) = delete; FileLock& operator=(const FileLock&) = delete; diff --git a/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/mman.hpp b/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/mman.hpp index b96f2067dc..6d1c44b453 100644 --- a/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/mman.hpp +++ b/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/mman.hpp @@ -20,5 +20,6 @@ #include int iox_shm_open(const char* name, int oflag, mode_t mode); +int iox_shm_unlink(const char* name); -#endif // IOX_HOOFS_LINUX_PLATFORM_MMAN_HPP \ No newline at end of file +#endif // IOX_HOOFS_LINUX_PLATFORM_MMAN_HPP diff --git a/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/platform_settings.hpp b/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/platform_settings.hpp index 022dd89b05..bf29ea9f2f 100644 --- a/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/platform_settings.hpp +++ b/iceoryx_hoofs/platform/linux/include/iceoryx_hoofs/platform/platform_settings.hpp @@ -17,6 +17,7 @@ #define IOX_HOOFS_LINUX_PLATFORM_PLATFORM_SETTINGS_HPP #include +#include namespace iox { @@ -27,11 +28,16 @@ class UnixDomainSocket; namespace platform { +constexpr uint64_t IOX_MAX_FILENAME_LENGTH = 255U; +constexpr uint64_t IOX_MAX_PATH_LENGTH = 1023U; constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true; +constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = PATH_MAX; constexpr const char IOX_PATH_SEPARATORS[] = "/"; constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 4096; -constexpr char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/"; +constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/"; +constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/tmp/"; using IoxIpcChannelType = iox::posix::UnixDomainSocket; } // namespace platform } // namespace iox + #endif // IOX_HOOFS_LINUX_PLATFORM_PLATFORM_SETTINGS_HPP diff --git a/iceoryx_hoofs/platform/linux/source/mman.cpp b/iceoryx_hoofs/platform/linux/source/mman.cpp index 7267e5869f..586af07dd3 100644 --- a/iceoryx_hoofs/platform/linux/source/mman.cpp +++ b/iceoryx_hoofs/platform/linux/source/mman.cpp @@ -20,3 +20,8 @@ int iox_shm_open(const char* name, int oflag, mode_t mode) { return shm_open(name, oflag, mode); } + +int iox_shm_unlink(const char* name) +{ + return shm_unlink(name); +} diff --git a/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/mman.hpp b/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/mman.hpp index 7df0e4ff93..0fc8cfa8bf 100644 --- a/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/mman.hpp +++ b/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/mman.hpp @@ -20,5 +20,6 @@ #include int iox_shm_open(const char* name, int oflag, mode_t mode); +int iox_shm_unlink(const char* name); -#endif // IOX_HOOFS_MAC_PLATFORM_MMAN_HPP \ No newline at end of file +#endif // IOX_HOOFS_MAC_PLATFORM_MMAN_HPP diff --git a/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/platform_settings.hpp b/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/platform_settings.hpp index 323804f826..5d7206bd3f 100644 --- a/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/platform_settings.hpp +++ b/iceoryx_hoofs/platform/mac/include/iceoryx_hoofs/platform/platform_settings.hpp @@ -27,10 +27,16 @@ class UnixDomainSocket; namespace platform { +constexpr uint64_t IOX_MAX_FILENAME_LENGTH = 255U; +constexpr uint64_t IOX_MAX_PATH_LENGTH = 1023U; constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true; +// it should be SHM_NAME_MAX but it is unknown in which header this define +// is defined +constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = 255U; constexpr const char IOX_PATH_SEPARATORS[] = "/"; constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 2048; -constexpr char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/"; +constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/"; +constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/tmp/"; using IoxIpcChannelType = iox::posix::UnixDomainSocket; } // namespace platform } // namespace iox diff --git a/iceoryx_hoofs/platform/mac/source/mman.cpp b/iceoryx_hoofs/platform/mac/source/mman.cpp index 7267e5869f..fb253e4a3c 100644 --- a/iceoryx_hoofs/platform/mac/source/mman.cpp +++ b/iceoryx_hoofs/platform/mac/source/mman.cpp @@ -16,7 +16,24 @@ #include "iceoryx_hoofs/platform/mman.hpp" +#include +#include + int iox_shm_open(const char* name, int oflag, mode_t mode) { return shm_open(name, oflag, mode); } + +int iox_shm_unlink(const char* name) +{ + int state = shm_unlink(name); + // according to mac os shm_unlink sets errno to ENOENT when the name is invalid + // and never EINVAL - but it is actually set when ENOENT should be set. + // See: + // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/shm_unlink.2.html + if (errno == EINVAL) + { + errno = ENOENT; + } + return state; +} diff --git a/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/mman.hpp b/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/mman.hpp index c743599f82..e1ba26da95 100644 --- a/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/mman.hpp +++ b/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/mman.hpp @@ -20,5 +20,6 @@ #include int iox_shm_open(const char* name, int oflag, mode_t mode); +int iox_shm_unlink(const char* name); -#endif // IOX_HOOFS_QNX_PLATFORM_MMAN_HPP \ No newline at end of file +#endif // IOX_HOOFS_QNX_PLATFORM_MMAN_HPP diff --git a/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/platform_settings.hpp b/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/platform_settings.hpp index 26888bcdf6..a506bc5431 100644 --- a/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/platform_settings.hpp +++ b/iceoryx_hoofs/platform/qnx/include/iceoryx_hoofs/platform/platform_settings.hpp @@ -27,10 +27,14 @@ class UnixDomainSocket; namespace platform { +constexpr uint64_t IOX_MAX_FILENAME_LENGTH = 255U; +constexpr uint64_t IOX_MAX_PATH_LENGTH = 1023U; constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true; +constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = 1024U; constexpr const char IOX_PATH_SEPARATORS[] = "/"; constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 4096; -constexpr char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/"; +constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/"; +constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/var/lock/"; using IoxIpcChannelType = iox::posix::UnixDomainSocket; } // namespace platform } // namespace iox diff --git a/iceoryx_hoofs/platform/qnx/source/mman.cpp b/iceoryx_hoofs/platform/qnx/source/mman.cpp index 7267e5869f..586af07dd3 100644 --- a/iceoryx_hoofs/platform/qnx/source/mman.cpp +++ b/iceoryx_hoofs/platform/qnx/source/mman.cpp @@ -20,3 +20,8 @@ int iox_shm_open(const char* name, int oflag, mode_t mode) { return shm_open(name, oflag, mode); } + +int iox_shm_unlink(const char* name) +{ + return shm_unlink(name); +} diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/handle_translator.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/handle_translator.hpp new file mode 100644 index 0000000000..e2227ed3cf --- /dev/null +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/handle_translator.hpp @@ -0,0 +1,41 @@ +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// +// Licensed 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. +// +// SPDX-License-Identifier: Apache-2.0 +#ifndef IOX_HOOFS_WIN_PLATFORM_HANDLE_TRANSLATOR_HPP +#define IOX_HOOFS_WIN_PLATFORM_HANDLE_TRANSLATOR_HPP + +#include "iceoryx_hoofs/platform/windows.hpp" +#include + +/// @brief In windows file handles have the type HANDLE (void*) in linux it is +/// usually an int. To establish the portability we keep track of the +/// windows handles and assign them a unique int so that they can be used +/// in a platform independent manner. +/// This class translates a windows handle of type HANDLE to its linux +/// file handle int pendant. +class HandleTranslator +{ + public: + static HandleTranslator& getInstance() noexcept; + HANDLE get(const int handle) const noexcept; + int add(HANDLE handle) noexcept; + void remove(const int handle) noexcept; + + private: + HandleTranslator() noexcept = default; + std::vector m_handleList; +}; + +#endif diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/ipc_handle_manager.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/ipc_handle_manager.hpp new file mode 100644 index 0000000000..765d75702a --- /dev/null +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/ipc_handle_manager.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// +// Licensed 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. +// +// SPDX-License-Identifier: Apache-2.0 +#ifndef IOX_HOOFS_WIN_PLATFORM_IPC_HANDLE_MANAGER_HPP +#define IOX_HOOFS_WIN_PLATFORM_IPC_HANDLE_MANAGER_HPP + +#include "iceoryx_hoofs/platform/unique_system_id.hpp" +#include "iceoryx_hoofs/platform/windows.hpp" +#include + + +enum class OwnerShip +{ + OWN, + LOAN, +}; + +struct IpcHandle_t +{ + OwnerShip ownerShip = OwnerShip::LOAN; + HANDLE handle = nullptr; +}; + +class IpcHandleManager +{ + public: + ~IpcHandleManager() noexcept; + + bool getHandle(const UniqueSystemId& id, HANDLE& handle) noexcept; + void addHandle(const UniqueSystemId& id, const OwnerShip ownerShip, HANDLE handle) noexcept; + void removeHandle(const UniqueSystemId& id) noexcept; + + private: + std::map ipcHandles; +}; + +#endif diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/mman.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/mman.hpp index ae6f1af4c0..7576fee2a4 100644 --- a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/mman.hpp +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/mman.hpp @@ -42,5 +42,5 @@ int munmap(void* addr, size_t length); int iox_shm_open(const char* name, int oflag, mode_t mode); -int shm_unlink(const char* name); +int iox_shm_unlink(const char* name); #endif // IOX_HOOFS_WIN_PLATFORM_MMAN_HPP diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_correction.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_correction.hpp index eca8cf5203..5fc5a8f320 100644 --- a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_correction.hpp +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_correction.hpp @@ -35,3 +35,4 @@ #undef interface #undef CreateSemaphore #undef NO_ERROR +#undef OPEN_EXISTING diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_settings.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_settings.hpp index 055c78e13e..19877b71f1 100644 --- a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_settings.hpp +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/platform_settings.hpp @@ -28,13 +28,17 @@ class NamedPipe; namespace platform { constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = false; +constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = 255U; // yes, windows has two possible path separators! constexpr const char IOX_PATH_SEPARATORS[] = "\\/"; // unix domain sockets are not supported in windows but the variables have to be defined // so that the code with stub implementation at least compiles constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 1024U; constexpr char IOX_UDS_SOCKET_PATH_PREFIX[] = ""; +constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "C:\\Windows\\Temp\\"; using IoxIpcChannelType = iox::posix::NamedPipe; +constexpr uint64_t IOX_MAX_FILENAME_LENGTH = 255U; +constexpr uint64_t IOX_MAX_PATH_LENGTH = 255U; namespace win32 { diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/pthread.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/pthread.hpp index b54821a277..25f004faa1 100644 --- a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/pthread.hpp +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/pthread.hpp @@ -17,6 +17,7 @@ #ifndef IOX_HOOFS_WIN_PLATFORM_PTHREAD_HPP #define IOX_HOOFS_WIN_PLATFORM_PTHREAD_HPP +#include "iceoryx_hoofs/platform/unique_system_id.hpp" #include "iceoryx_hoofs/platform/win32_errorHandling.hpp" #include "iceoryx_hoofs/platform/windows.hpp" @@ -30,8 +31,9 @@ struct pthread_mutex_t { - HANDLE handle; + HANDLE handle = INVALID_HANDLE_VALUE; bool isInterprocessMutex = false; + UniqueSystemId uniqueId; }; struct pthread_mutexattr_t diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/semaphore.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/semaphore.hpp index 7451932527..e3f0a68c7d 100644 --- a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/semaphore.hpp +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/semaphore.hpp @@ -20,11 +20,12 @@ #include "iceoryx_hoofs/platform/fcntl.hpp" #include "iceoryx_hoofs/platform/time.hpp" #include "iceoryx_hoofs/platform/types.hpp" +#include "iceoryx_hoofs/platform/unique_system_id.hpp" #include "iceoryx_hoofs/platform/win32_errorHandling.hpp" #include "iceoryx_hoofs/platform/windows.hpp" - #include +#include #include #include #include @@ -35,6 +36,8 @@ struct iox_sem_t { HANDLE handle{nullptr}; + bool isInterprocessSemaphore{false}; + UniqueSystemId uniqueId; }; static constexpr LONG MAX_SEMAPHORE_VALUE = LONG_MAX; static constexpr int MAX_SEMAPHORE_NAME_LENGTH = 128; diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unique_system_id.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unique_system_id.hpp new file mode 100644 index 0000000000..25fb8fc155 --- /dev/null +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unique_system_id.hpp @@ -0,0 +1,50 @@ +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// +// Licensed 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. +// +// SPDX-License-Identifier: Apache-2.0 +#ifndef IOX_HOOFS_WIN_PLATFORM_UNIQUE_SYSTEM_ID_HPP +#define IOX_HOOFS_WIN_PLATFORM_UNIQUE_SYSTEM_ID_HPP + +#include +#include +#include + +/// @brief IPC constructs in windows like mutex, semaphore etc are hard to handle +/// and it is even harder when this should be done in a platform independent +/// manner. +/// An easier approach is to create named mutex and semaphores and open them +/// in every process which requires access. This requires that the mutex and +/// semaphores are created with a system wide unique name. This class generates +/// a system wide unique id which looks like the following: +/// ProcessId_Timestamp_ProcessUniqueCounter. +class UniqueSystemId +{ + public: + UniqueSystemId() noexcept; + + operator std::string() const noexcept; + + bool operator==(const UniqueSystemId& rhs) const noexcept; + bool operator!=(const UniqueSystemId& rhs) const noexcept; + bool operator<(const UniqueSystemId& rhs) const noexcept; + + private: + uint64_t m_processId = 0U; + uint64_t m_timestamp = 0U; + uint64_t m_sequenceNumber = 0U; + + static std::atomic sequenceCounter; +}; + +#endif diff --git a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unistd.hpp b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unistd.hpp index 86e8008285..66fc6437bd 100644 --- a/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unistd.hpp +++ b/iceoryx_hoofs/platform/win/include/iceoryx_hoofs/platform/unistd.hpp @@ -26,22 +26,6 @@ #define _SC_PAGESIZE 1 #define STDERR_FILENO 2 -class HandleTranslator -{ - public: - static HandleTranslator& getInstance() noexcept; - HANDLE get(const int handle) const noexcept; - int add(HANDLE handle) noexcept; - void remove(int handle) noexcept; - - private: - struct handle_t - { - HANDLE windowsHandle; - }; - std::vector m_handleList; -}; - int ftruncate(int fildes, off_t length); long sysconf(int name); diff --git a/iceoryx_hoofs/platform/win/source/file.cpp b/iceoryx_hoofs/platform/win/source/file.cpp index 9d5133ba6b..4526a6ed00 100644 --- a/iceoryx_hoofs/platform/win/source/file.cpp +++ b/iceoryx_hoofs/platform/win/source/file.cpp @@ -15,8 +15,16 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/platform/file.hpp" +#include "iceoryx_hoofs/platform/handle_translator.hpp" +#include "iceoryx_hoofs/platform/win32_errorHandling.hpp" +#include "iceoryx_hoofs/platform/windows.hpp" int iox_flock(int fd, int op) { + HANDLE handle = HandleTranslator::getInstance().get(fd); + if (Win32Call(LockFile, handle, 0, 0, 0, 0).value == FALSE) + { + return -1; + } return 0; } diff --git a/iceoryx_hoofs/platform/win/source/fnctl.cpp b/iceoryx_hoofs/platform/win/source/fnctl.cpp index 95835a82e7..54a607e6c2 100644 --- a/iceoryx_hoofs/platform/win/source/fnctl.cpp +++ b/iceoryx_hoofs/platform/win/source/fnctl.cpp @@ -15,8 +15,27 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/platform/fcntl.hpp" +#include "iceoryx_hoofs/platform/handle_translator.hpp" +#include "iceoryx_hoofs/platform/win32_errorHandling.hpp" int iox_open(const char* pathname, int flags, mode_t mode) { - return 0; + auto handle = Win32Call(CreateFileA, + pathname, + GENERIC_WRITE, + 0, + static_cast(NULL), + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + static_cast(NULL)) + .value; + + if (handle == INVALID_HANDLE_VALUE) + { + fprintf(stderr, "unable to create file \"%s\"\n", pathname); + errno = EWOULDBLOCK; + return -1; + } + + return HandleTranslator::getInstance().add(handle); } diff --git a/iceoryx_hoofs/platform/win/source/handle_translator.cpp b/iceoryx_hoofs/platform/win/source/handle_translator.cpp new file mode 100644 index 0000000000..526a82279f --- /dev/null +++ b/iceoryx_hoofs/platform/win/source/handle_translator.cpp @@ -0,0 +1,48 @@ +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// +// Licensed 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "iceoryx_hoofs/platform/handle_translator.hpp" + +HandleTranslator& HandleTranslator::getInstance() noexcept +{ + static HandleTranslator globalHandleTranslator; + return globalHandleTranslator; +} + +HANDLE HandleTranslator::get(const int handle) const noexcept +{ + return m_handleList[static_cast(handle)]; +} + +int HandleTranslator::add(HANDLE handle) noexcept +{ + for (int64_t limit = m_handleList.size(), k = 0; k < limit; ++k) + { + if (m_handleList[k] == nullptr) + { + m_handleList[k] = handle; + return k; + } + } + + m_handleList.emplace_back(handle); + return m_handleList.size() - 1; +} + +void HandleTranslator::remove(const int handle) noexcept +{ + m_handleList[static_cast(handle)] = nullptr; +} diff --git a/iceoryx_hoofs/platform/win/source/ipc_handle_manager.cpp b/iceoryx_hoofs/platform/win/source/ipc_handle_manager.cpp new file mode 100644 index 0000000000..7ffd1f90e0 --- /dev/null +++ b/iceoryx_hoofs/platform/win/source/ipc_handle_manager.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// +// Licensed 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "iceoryx_hoofs/platform/ipc_handle_manager.hpp" + +IpcHandleManager::~IpcHandleManager() noexcept +{ + for (auto& handle : ipcHandles) + { + if (handle.second.ownerShip == OwnerShip::LOAN) + { + CloseHandle(handle.second.handle); + } + } +} + +bool IpcHandleManager::getHandle(const UniqueSystemId& id, HANDLE& handle) noexcept +{ + auto iter = ipcHandles.find(id); + if (iter != ipcHandles.end()) + { + handle = iter->second.handle; + return true; + } + return false; +} + +void IpcHandleManager::addHandle(const UniqueSystemId& id, const OwnerShip ownerShip, HANDLE handle) noexcept +{ + ipcHandles[id] = IpcHandle_t{ownerShip, handle}; +} + +void IpcHandleManager::removeHandle(const UniqueSystemId& id) noexcept +{ + auto iter = ipcHandles.find(id); + if (iter != ipcHandles.end()) + { + ipcHandles.erase(iter); + } +} diff --git a/iceoryx_hoofs/platform/win/source/mman.cpp b/iceoryx_hoofs/platform/win/source/mman.cpp index f118d12cc3..470b47cd04 100644 --- a/iceoryx_hoofs/platform/win/source/mman.cpp +++ b/iceoryx_hoofs/platform/win/source/mman.cpp @@ -15,6 +15,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/platform/mman.hpp" +#include "iceoryx_hoofs/platform/handle_translator.hpp" #include "iceoryx_hoofs/platform/platform_settings.hpp" #include "iceoryx_hoofs/platform/win32_errorHandling.hpp" @@ -58,7 +59,7 @@ int iox_shm_open(const char* name, int oflag, mode_t mode) { HANDLE sharedMemoryHandle{nullptr}; - if (oflag & O_CREAT) // O_EXCL + if (oflag & O_CREAT) { // we do not yet support ACL and rights for data partitions in windows // DWORD access = (oflag & O_RDWR) ? PAGE_READWRITE : PAGE_READONLY; @@ -78,6 +79,7 @@ int iox_shm_open(const char* name, int oflag, mode_t mode) if (oflag & O_EXCL && result.error == ERROR_ALREADY_EXISTS) { + errno = EEXIST; if (sharedMemoryHandle != nullptr) { Win32Call(CloseHandle, sharedMemoryHandle).value; @@ -108,7 +110,7 @@ int iox_shm_open(const char* name, int oflag, mode_t mode) return HandleTranslator::getInstance().add(sharedMemoryHandle); } -int shm_unlink(const char* name) +int iox_shm_unlink(const char* name) { auto iter = openedSharedMemorySegments.find(name); if (iter != openedSharedMemorySegments.end()) diff --git a/iceoryx_hoofs/platform/win/source/pthread.cpp b/iceoryx_hoofs/platform/win/source/pthread.cpp index 964f1d2767..257fef06ea 100644 --- a/iceoryx_hoofs/platform/win/source/pthread.cpp +++ b/iceoryx_hoofs/platform/win/source/pthread.cpp @@ -15,12 +15,15 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/platform/pthread.hpp" +#include "iceoryx_hoofs/platform/ipc_handle_manager.hpp" #include "iceoryx_hoofs/platform/win32_errorHandling.hpp" #include "iceoryx_hoofs/platform/windows.hpp" #include #include +static IpcHandleManager ipcMutexHandleManager; + int iox_pthread_setname_np(pthread_t thread, const char* name) { DWORD threadId = Win32Call(GetThreadId, static_cast(thread)).value; @@ -86,72 +89,98 @@ int pthread_mutex_destroy(pthread_mutex_t* mutex) return 0; } -int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr) +static HANDLE createWin32Mutex(LPSECURITY_ATTRIBUTES securityAttributes, BOOL initialOwner, LPCSTR name) { - mutex->isInterprocessMutex = (attr != NULL && attr->isInterprocessMutex); + return Win32Call(CreateMutexA, securityAttributes, initialOwner, name).value; +} + +static std::string generateMutexName(const UniqueSystemId& id) noexcept +{ + return "iox_mutex_" + static_cast(id); +} +static HANDLE acquireMutexHandle(pthread_mutex_t* mutex) +{ if (!mutex->isInterprocessMutex) { - mutex->handle = Win32Call(CreateMutexA, - static_cast(NULL), - static_cast(FALSE), - static_cast(NULL)) - .value; + return mutex->handle; + } + HANDLE newHandle; + if (ipcMutexHandleManager.getHandle(mutex->uniqueId, newHandle)) + { + return newHandle; + } - if (mutex->handle == NULL) - { - return EINVAL; - } + newHandle = Win32Call(OpenMutexA, MUTEX_ALL_ACCESS, false, generateMutexName(mutex->uniqueId).c_str()).value; + if (newHandle == nullptr) + { + fprintf(stderr, + "interprocess mutex %s is corrupted - segmentation fault immenent\n", + generateMutexName(mutex->uniqueId).c_str()); + return nullptr; } - return 0; + + ipcMutexHandleManager.addHandle(mutex->uniqueId, OwnerShip::LOAN, newHandle); + return newHandle; } -int pthread_mutex_lock(pthread_mutex_t* mutex) +int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr) { + mutex->isInterprocessMutex = (attr != NULL && attr->isInterprocessMutex); + if (!mutex->isInterprocessMutex) { - DWORD waitResult = Win32Call(WaitForSingleObject, mutex->handle, INFINITE).value; - - switch (waitResult) + mutex->handle = createWin32Mutex(NULL, FALSE, NULL); + } + else + { + mutex->handle = createWin32Mutex(NULL, FALSE, generateMutexName(mutex->uniqueId).c_str()); + if (mutex->handle != nullptr) { - case WAIT_OBJECT_0: - return 0; - default: - return EINVAL; + ipcMutexHandleManager.addHandle(mutex->uniqueId, OwnerShip::OWN, mutex->handle); } } + + return (mutex->handle == nullptr) ? EINVAL : 0; +} + +int pthread_mutex_lock(pthread_mutex_t* mutex) +{ + DWORD waitResult = Win32Call(WaitForSingleObject, acquireMutexHandle(mutex), INFINITE).value; + + switch (waitResult) + { + case WAIT_OBJECT_0: + return 0; + default: + return EINVAL; + } return 0; } int pthread_mutex_trylock(pthread_mutex_t* mutex) { - if (!mutex->isInterprocessMutex) - { - DWORD waitResult = Win32Call(WaitForSingleObject, mutex->handle, 0).value; + DWORD waitResult = Win32Call(WaitForSingleObject, acquireMutexHandle(mutex), 0).value; - switch (waitResult) - { - case WAIT_TIMEOUT: - return EBUSY; - case WAIT_OBJECT_0: - return 0; - default: - return EINVAL; - } + switch (waitResult) + { + case WAIT_TIMEOUT: + return EBUSY; + case WAIT_OBJECT_0: + return 0; + default: + return EINVAL; } return 0; } int pthread_mutex_unlock(pthread_mutex_t* mutex) { - if (!mutex->isInterprocessMutex) + auto releaseResult = Win32Call(ReleaseMutex, acquireMutexHandle(mutex)).value; + if (!releaseResult) { - auto releaseResult = Win32Call(ReleaseMutex, mutex->handle).value; - if (!releaseResult) - { - return EPERM; - } + return EPERM; } return 0; } diff --git a/iceoryx_hoofs/platform/win/source/semaphore.cpp b/iceoryx_hoofs/platform/win/source/semaphore.cpp index c87447cb3f..935231c212 100644 --- a/iceoryx_hoofs/platform/win/source/semaphore.cpp +++ b/iceoryx_hoofs/platform/win/source/semaphore.cpp @@ -16,18 +16,53 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/platform/semaphore.hpp" +#include "iceoryx_hoofs/platform/ipc_handle_manager.hpp" #include +static IpcHandleManager ipcSemaphoreHandleManager; + +static std::string generateSemaphoreName(const UniqueSystemId& id) +{ + return "iox_semaphore_" + static_cast(id); +} + +static HANDLE acquireSemaphoreHandle(iox_sem_t* sem) +{ + if (!sem->isInterprocessSemaphore) + { + return sem->handle; + } + + HANDLE newHandle; + if (ipcSemaphoreHandleManager.getHandle(sem->uniqueId, newHandle)) + { + return newHandle; + } + + newHandle = + Win32Call(OpenSemaphoreA, SEMAPHORE_ALL_ACCESS, false, generateSemaphoreName(sem->uniqueId).c_str()).value; + if (newHandle == nullptr) + { + fprintf(stderr, + "interprocess semaphore %s is corrupted - segmentation fault immenent\n", + generateSemaphoreName(sem->uniqueId).c_str()); + return nullptr; + } + + ipcSemaphoreHandleManager.addHandle(sem->uniqueId, OwnerShip::LOAN, newHandle); + return newHandle; +} + int iox_sem_getvalue(iox_sem_t* sem, int* sval) { LONG previousValue; - auto waitResult = Win32Call(WaitForSingleObject, sem->handle, 0).value; + auto waitResult = Win32Call(WaitForSingleObject, acquireSemaphoreHandle(sem), 0).value; switch (waitResult) { case WAIT_OBJECT_0: { - auto releaseResult = Win32Call(ReleaseSemaphore, sem->handle, 1, &previousValue).value; + auto releaseResult = Win32Call(ReleaseSemaphore, acquireSemaphoreHandle(sem), 1, &previousValue).value; if (releaseResult) { *sval = previousValue + 1; @@ -49,19 +84,19 @@ int iox_sem_getvalue(iox_sem_t* sem, int* sval) int iox_sem_post(iox_sem_t* sem) { - int retVal = Win32Call(ReleaseSemaphore, sem->handle, 1, nullptr).value; + int retVal = Win32Call(ReleaseSemaphore, acquireSemaphoreHandle(sem), 1, nullptr).value; return (retVal != 0) ? 0 : -1; } int iox_sem_wait(iox_sem_t* sem) { - int retVal = Win32Call(WaitForSingleObject, sem->handle, INFINITE).value; + int retVal = Win32Call(WaitForSingleObject, acquireSemaphoreHandle(sem), INFINITE).value; return (retVal == WAIT_OBJECT_0) ? 0 : -1; } int iox_sem_trywait(iox_sem_t* sem) { - int retVal = Win32Call(WaitForSingleObject, sem->handle, 0).value; + int retVal = Win32Call(WaitForSingleObject, acquireSemaphoreHandle(sem), 0).value; if (retVal != WAIT_OBJECT_0) { errno = EAGAIN; @@ -90,7 +125,8 @@ int iox_sem_timedwait(iox_sem_t* sem, const struct timespec* abs_timeout) + HALF_MILLI_SECOND_ROUNDING_CORRECTION_IN_NS) / NANO_SECONDS_PER_MILLI_SECOND; - auto state = Win32Call(WaitForSingleObject, sem->handle, (milliseconds == 0) ? 1 : milliseconds).value; + auto state = + Win32Call(WaitForSingleObject, acquireSemaphoreHandle(sem), (milliseconds == 0) ? 1 : milliseconds).value; if (state == WAIT_TIMEOUT) { errno = ETIMEDOUT; @@ -101,18 +137,23 @@ int iox_sem_timedwait(iox_sem_t* sem, const struct timespec* abs_timeout) int iox_sem_close(iox_sem_t* sem) { - int retVal = Win32Call(CloseHandle, sem->handle).value ? 0 : -1; + // we close a named semaphore, therefore we do not need to perform an ipc cleanup + int retVal = Win32Call(CloseHandle, acquireSemaphoreHandle(sem)).value ? 0 : -1; delete sem; return (retVal) ? 0 : -1; } int iox_sem_destroy(iox_sem_t* sem) { - CloseHandle(sem->handle); + CloseHandle(acquireSemaphoreHandle(sem)); + if (sem->isInterprocessSemaphore) + { + ipcSemaphoreHandleManager.removeHandle(sem->uniqueId); + } return 0; } -HANDLE __sem_create_win32_semaphore(LONG value, LPCSTR name) +static HANDLE sem_create_win32_semaphore(LONG value, LPCSTR name) { SECURITY_ATTRIBUTES securityAttribute; SECURITY_DESCRIPTOR securityDescriptor; @@ -136,15 +177,23 @@ HANDLE __sem_create_win32_semaphore(LONG value, LPCSTR name) return returnValue; } - int iox_sem_init(iox_sem_t* sem, int pshared, unsigned int value) { - sem->handle = __sem_create_win32_semaphore(value, nullptr); - if (sem->handle != nullptr) + sem->isInterprocessSemaphore = (pshared == 1); + if (sem->isInterprocessSemaphore) { - return 0; + sem->handle = sem_create_win32_semaphore(value, generateSemaphoreName(sem->uniqueId).c_str()); + if (sem->handle != nullptr) + { + ipcSemaphoreHandleManager.addHandle(sem->uniqueId, OwnerShip::OWN, sem->handle); + } + } + else + { + sem->handle = sem_create_win32_semaphore(value, nullptr); } - return -1; + + return (sem->handle != nullptr) ? 0 : -1; } int iox_sem_unlink(const char* name) @@ -170,7 +219,7 @@ iox_sem_t* iox_sem_open_impl(const char* name, int oflag, ...) // mode_t mode, u unsigned int value = va_arg(va, unsigned int); va_end(va); - sem->handle = __sem_create_win32_semaphore(value, name); + sem->handle = sem_create_win32_semaphore(value, name); if (oflag & O_EXCL && GetLastError() == ERROR_ALREADY_EXISTS) { iox_sem_close(sem); diff --git a/iceoryx_hoofs/platform/win/source/unique_system_id.cpp b/iceoryx_hoofs/platform/win/source/unique_system_id.cpp new file mode 100644 index 0000000000..e879e257e3 --- /dev/null +++ b/iceoryx_hoofs/platform/win/source/unique_system_id.cpp @@ -0,0 +1,53 @@ +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. +// +// Licensed 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. +// +// SPDX-License-Identifier: Apache-2.0 + +#include "iceoryx_hoofs/platform/unique_system_id.hpp" +#include "iceoryx_hoofs/platform/windows.hpp" + +#include +#include + + +std::atomic UniqueSystemId::sequenceCounter{0U}; + +UniqueSystemId::UniqueSystemId() noexcept + : m_processId{GetCurrentProcessId()} + , m_timestamp{static_cast(std::chrono::system_clock::now().time_since_epoch().count())} + , m_sequenceNumber{sequenceCounter.fetch_add(1U, std::memory_order_relaxed)} +{ +} + +bool UniqueSystemId::operator==(const UniqueSystemId& rhs) const noexcept +{ + return m_processId == rhs.m_processId && m_timestamp == rhs.m_timestamp && m_sequenceNumber == rhs.m_sequenceNumber; +} + +bool UniqueSystemId::operator!=(const UniqueSystemId& rhs) const noexcept +{ + return !(*this == rhs); +} + +bool UniqueSystemId::operator<(const UniqueSystemId& rhs) const noexcept +{ + return (m_processId < rhs.m_processId) || (m_processId == rhs.m_processId && m_timestamp < rhs.m_timestamp) + || (m_processId == rhs.m_processId && m_timestamp == rhs.m_timestamp + && m_sequenceNumber < rhs.m_sequenceNumber); +} + +UniqueSystemId::operator std::string() const noexcept +{ + return std::to_string(m_processId) + "_" + std::to_string(m_timestamp) + "_" + std::to_string(m_sequenceNumber); +} diff --git a/iceoryx_hoofs/platform/win/source/unistd.cpp b/iceoryx_hoofs/platform/win/source/unistd.cpp index 71010c3df8..c36281ce8d 100644 --- a/iceoryx_hoofs/platform/win/source/unistd.cpp +++ b/iceoryx_hoofs/platform/win/source/unistd.cpp @@ -16,39 +16,9 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/platform/unistd.hpp" +#include "iceoryx_hoofs/platform/handle_translator.hpp" #include "iceoryx_hoofs/platform/win32_errorHandling.hpp" -HandleTranslator& HandleTranslator::getInstance() noexcept -{ - static HandleTranslator globalHandleTranslator; - return globalHandleTranslator; -} - -HANDLE HandleTranslator::get(const int handle) const noexcept -{ - return m_handleList[static_cast(handle)].windowsHandle; -} - -int HandleTranslator::add(HANDLE handle) noexcept -{ - for (int64_t limit = m_handleList.size(), k = 0; k < limit; ++k) - { - if (m_handleList[k].windowsHandle == nullptr) - { - m_handleList[k].windowsHandle = handle; - return k; - } - } - - m_handleList.emplace_back(handle_t{handle}); - return m_handleList.size() - 1; -} - -void HandleTranslator::remove(int handle) noexcept -{ - m_handleList[static_cast(handle)].windowsHandle = nullptr; -} - int ftruncate(int fildes, off_t length) { return 0; diff --git a/iceoryx_hoofs/source/posix_wrapper/file_lock.cpp b/iceoryx_hoofs/source/posix_wrapper/file_lock.cpp index d332f07a2f..f72812220c 100644 --- a/iceoryx_hoofs/source/posix_wrapper/file_lock.cpp +++ b/iceoryx_hoofs/source/posix_wrapper/file_lock.cpp @@ -15,6 +15,7 @@ // SPDX-License-Identifier: Apache-2.0 #include "iceoryx_hoofs/posix_wrapper/file_lock.hpp" +#include "iceoryx_hoofs/cxx/helplets.hpp" #include "iceoryx_hoofs/platform/errno.hpp" #include "iceoryx_hoofs/platform/fcntl.hpp" #include "iceoryx_hoofs/platform/file.hpp" @@ -39,11 +40,11 @@ FileLock::FileLock(const FileName_t& name) noexcept cxx::expected FileLock::initializeFileLock() noexcept { - if (m_name.empty()) + if (!cxx::isValidFilePath(m_name)) { - return cxx::error(FileLockError::NO_FILE_NAME_PROVIDED); + return cxx::error(FileLockError::INVALID_FILE_NAME); } - PathName_t fullPath(PATH_PREFIX + m_name + ".lock"); + PathName_t fullPath(platform::IOX_LOCK_FILE_PATH_PREFIX + m_name + ".lock"); constexpr int createFileForReadWrite = O_CREAT | O_RDWR; mode_t userReadWriteAccess = S_IRUSR | S_IWUSR; @@ -183,7 +184,7 @@ FileLockError FileLock::convertErrnoToFileLockError(const int32_t errnum) const } case ENOENT: { - std::cerr << "directory \"" << PATH_PREFIX << "\"" + std::cerr << "directory \"" << platform::IOX_LOCK_FILE_PATH_PREFIX << "\"" << " does not exist. Please create it as described in the filesystem hierarchy standard." << std::endl; return FileLockError::NO_SUCH_DIRECTORY; diff --git a/iceoryx_hoofs/source/posix_wrapper/named_pipe.cpp b/iceoryx_hoofs/source/posix_wrapper/named_pipe.cpp index 4e66527d60..e8e36a9109 100644 --- a/iceoryx_hoofs/source/posix_wrapper/named_pipe.cpp +++ b/iceoryx_hoofs/source/posix_wrapper/named_pipe.cpp @@ -89,7 +89,7 @@ NamedPipe::NamedPipe(const IpcChannelName_t& name, // m_messages. when we add the alignment it is guaranteed that enough memory should be available. sizeof(MessageQueue_t) + alignof(MessageQueue_t), AccessMode::READ_WRITE, - (channelSide == IpcChannelSide::SERVER) ? OwnerShip::MINE : OwnerShip::OPEN_EXISTING_SHM, + (channelSide == IpcChannelSide::SERVER) ? OpenMode::OPEN_OR_CREATE : OpenMode::OPEN_EXISTING, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); if (sharedMemory.has_error()) @@ -166,16 +166,16 @@ cxx::expected NamedPipe::isOutdated() noexcept cxx::expected NamedPipe::unlinkIfExists(const IpcChannelName_t& name) noexcept { constexpr int ERROR_CODE = -1; - auto unlinkCall = - posixCall(shm_unlink)(convertName(name).c_str()).failureReturnValue(ERROR_CODE).ignoreErrnos(ENOENT).evaluate(); + auto unlinkCall = posixCall(iox_shm_unlink)(convertName(name).c_str()) + .failureReturnValue(ERROR_CODE) + .ignoreErrnos(ENOENT) + .evaluate(); if (!unlinkCall.has_error()) { return cxx::success(unlinkCall->errnum != ENOENT); } - else - { - return cxx::error(IpcChannelError::INTERNAL_LOGIC_ERROR); - } + + return cxx::error(IpcChannelError::INTERNAL_LOGIC_ERROR); } cxx::expected NamedPipe::send(const std::string& message) const noexcept diff --git a/iceoryx_hoofs/source/posix_wrapper/shared_memory_object.cpp b/iceoryx_hoofs/source/posix_wrapper/shared_memory_object.cpp index 8ff51df6b4..5af7954cf5 100644 --- a/iceoryx_hoofs/source/posix_wrapper/shared_memory_object.cpp +++ b/iceoryx_hoofs/source/posix_wrapper/shared_memory_object.cpp @@ -32,7 +32,7 @@ namespace iox namespace posix { constexpr void* SharedMemoryObject::NO_ADDRESS_HINT; -constexpr uint64_t SIGBUS_ERROR_MESSAGE_LENGTH = 1024U; +constexpr uint64_t SIGBUS_ERROR_MESSAGE_LENGTH = 1024U + platform::IOX_MAX_SHM_NAME_LENGTH; static char sigbusErrorMessage[SIGBUS_ERROR_MESSAGE_LENGTH]; static std::mutex sigbusHandlerMutex; @@ -47,14 +47,14 @@ static void memsetSigbusHandler(int) SharedMemoryObject::SharedMemoryObject(const SharedMemory::Name_t& name, const uint64_t memorySizeInBytes, const AccessMode accessMode, - const OwnerShip ownerShip, + const OpenMode openMode, const void* baseAddressHint, const mode_t permissions) : m_memorySizeInBytes(cxx::align(memorySizeInBytes, Allocator::MEMORY_ALIGNMENT)) { m_isInitialized = true; - SharedMemory::create(name, accessMode, ownerShip, permissions, m_memorySizeInBytes) + SharedMemory::create(name, accessMode, openMode, permissions, m_memorySizeInBytes) .and_then([this](auto& sharedMemory) { m_sharedMemory.emplace(std::move(sharedMemory)); }) .or_else([this](auto&) { std::cerr << "Unable to create SharedMemoryObject since we could not acquire a SharedMemory resource" @@ -79,7 +79,7 @@ SharedMemoryObject::SharedMemoryObject(const SharedMemory::Name_t& name, std::cerr << "Unable to create a shared memory object with the following properties [ name = " << name << ", sizeInBytes = " << memorySizeInBytes << ", access mode = " << ACCESS_MODE_STRING[static_cast(accessMode)] - << ", ownership = " << OWNERSHIP_STRING[static_cast(ownerShip)] + << ", open mode = " << OPEN_MODE_STRING[static_cast(openMode)] << ", baseAddressHint = " << std::hex << baseAddressHint << ", permissions = " << std::bitset(permissions) << " ]" << std::endl; return; @@ -87,7 +87,7 @@ SharedMemoryObject::SharedMemoryObject(const SharedMemory::Name_t& name, m_allocator.emplace(m_memoryMap->getBaseAddress(), m_memorySizeInBytes); - if (ownerShip == OwnerShip::MINE && m_isInitialized) + if (m_isInitialized && m_sharedMemory->hasOwnership()) { std::clog << "Reserving " << m_memorySizeInBytes << " bytes in the shared memory [" << name << "]" << std::endl; if (platform::IOX_SHM_WRITE_ZEROS_ON_CREATION) @@ -102,12 +102,12 @@ SharedMemoryObject::SharedMemoryObject(const SharedMemory::Name_t& name, SIGBUS_ERROR_MESSAGE_LENGTH, "While setting the acquired shared memory to zero a fatal SIGBUS signal appeared caused by memset. The " "shared memory object with the following properties [ name = %s, sizeInBytes = %llu, access mode = %s, " - "ownership = %s, baseAddressHint = %p, permissions = %lu ] maybe requires more memory than it is " + "open mode = %s, baseAddressHint = %p, permissions = %lu ] maybe requires more memory than it is " "currently available in the system.\n", name.c_str(), static_cast(memorySizeInBytes), ACCESS_MODE_STRING[static_cast(accessMode)], - OWNERSHIP_STRING[static_cast(ownerShip)], + OPEN_MODE_STRING[static_cast(openMode)], baseAddressHint, std::bitset(permissions).to_ulong()); diff --git a/iceoryx_hoofs/source/posix_wrapper/shared_memory_object/shared_memory.cpp b/iceoryx_hoofs/source/posix_wrapper/shared_memory_object/shared_memory.cpp index f8012bb998..7f98a03ec7 100644 --- a/iceoryx_hoofs/source/posix_wrapper/shared_memory_object/shared_memory.cpp +++ b/iceoryx_hoofs/source/posix_wrapper/shared_memory_object/shared_memory.cpp @@ -35,10 +35,9 @@ namespace posix { SharedMemory::SharedMemory(const Name_t& name, const AccessMode accessMode, - const OwnerShip ownerShip, + const OpenMode openMode, const mode_t permissions, const uint64_t size) noexcept - : m_ownerShip(ownerShip) { m_isInitialized = true; // on qnx the current working directory will be added to the /dev/shmem path if the leading slash is missing @@ -58,18 +57,14 @@ SharedMemory::SharedMemory(const Name_t& name, if (m_isInitialized) { m_name = name; - int oflags = 0; - oflags |= (accessMode == AccessMode::READ_ONLY) ? O_RDONLY : O_RDWR; - oflags |= (ownerShip == OwnerShip::MINE) ? O_CREAT | O_EXCL : 0; - - m_isInitialized = open(oflags, permissions, size); + m_isInitialized = open(accessMode, openMode, permissions, size); } if (!m_isInitialized) { std::cerr << "Unable to create shared memory with the following properties [ name = " << name << ", access mode = " << ACCESS_MODE_STRING[static_cast(accessMode)] - << ", ownership = " << OWNERSHIP_STRING[static_cast(ownerShip)] + << ", open mode = " << OPEN_MODE_STRING[static_cast(openMode)] << ", mode = " << std::bitset(permissions) << ", sizeInBytes = " << size << " ]" << std::endl; return; @@ -81,21 +76,30 @@ SharedMemory::~SharedMemory() noexcept destroy(); } +int SharedMemory::getOflagsFor(const AccessMode accessMode, const OpenMode openMode) noexcept +{ + int oflags = 0; + oflags |= (accessMode == AccessMode::READ_ONLY) ? O_RDONLY : O_RDWR; + oflags |= (openMode != OpenMode::OPEN_EXISTING) ? O_CREAT : 0; + oflags |= (openMode == OpenMode::EXCLUSIVE_CREATE) ? O_EXCL : 0; + return oflags; +} + void SharedMemory::destroy() noexcept { if (m_isInitialized) { close(); unlink(); - reset(); } } void SharedMemory::reset() noexcept { m_isInitialized = false; + m_hasOwnership = false; m_name = Name_t(); - m_handle = -1; + m_handle = INVALID_HANDLE; } SharedMemory::SharedMemory(SharedMemory&& rhs) noexcept @@ -112,7 +116,7 @@ SharedMemory& SharedMemory::operator=(SharedMemory&& rhs) noexcept CreationPattern_t::operator=(std::move(rhs)); m_name = rhs.m_name; - m_ownerShip = std::move(rhs.m_ownerShip); + m_hasOwnership = std::move(rhs.m_hasOwnership); m_handle = std::move(rhs.m_handle); rhs.reset(); @@ -125,48 +129,72 @@ int32_t SharedMemory::getHandle() const noexcept return m_handle; } -bool SharedMemory::open(const int oflags, const mode_t permissions, const uint64_t size) noexcept +bool SharedMemory::hasOwnership() const noexcept { - cxx::Expects(static_cast(size) <= std::numeric_limits::max()); + return m_hasOwnership; +} +bool SharedMemory::open(const AccessMode accessMode, + const OpenMode openMode, + const mode_t permissions, + const uint64_t size) noexcept +{ + cxx::Expects(size <= static_cast(std::numeric_limits::max())); + + m_hasOwnership = (openMode == OpenMode::EXCLUSIVE_CREATE || openMode == OpenMode::PURGE_AND_CREATE + || openMode == OpenMode::OPEN_OR_CREATE); // the mask will be applied to the permissions, therefore we need to set it to 0 mode_t umaskSaved = umask(0U); { cxx::GenericRAII umaskGuard([&] { umask(umaskSaved); }); - // if we create the shm, cleanup old resources - if (oflags & O_CREAT) + if (openMode == OpenMode::PURGE_AND_CREATE) { - posixCall(shm_unlink)(m_name.c_str()) - .failureReturnValue(-1) - .ignoreErrnos(ENOENT) - .evaluate() - .and_then([this](auto& r) { - if (r.errnum != ENOENT) - { - std::cout << "SharedMemory still there, doing an unlink of " << m_name << std::endl; - } - }); + IOX_DISCARD_RESULT(posixCall(iox_shm_unlink)(m_name.c_str()) + .failureReturnValue(INVALID_HANDLE) + .ignoreErrnos(ENOENT) + .evaluate()); } - if (posixCall(iox_shm_open)(m_name.c_str(), oflags, permissions) - .failureReturnValue(-1) - .evaluate() - .and_then([this](auto& r) { m_handle = r.value; }) - .or_else([this](auto& r) { m_errorValue = this->errnoToEnum(r.errnum); }) - .has_error()) + auto result = posixCall(iox_shm_open)( + m_name.c_str(), + getOflagsFor(accessMode, + (openMode == OpenMode::OPEN_OR_CREATE) ? OpenMode::EXCLUSIVE_CREATE : openMode), + permissions) + .failureReturnValue(INVALID_HANDLE) + .suppressErrorMessagesForErrnos((openMode == OpenMode::OPEN_OR_CREATE) ? EEXIST : 0) + .evaluate(); + if (result.has_error()) { + // if it was not possible to create the shm exclusively someone else has the + // ownership and we just try to open it + if (openMode == OpenMode::OPEN_OR_CREATE && result.get_error().errnum == EEXIST) + { + m_hasOwnership = false; + result = posixCall(iox_shm_open)( + m_name.c_str(), getOflagsFor(accessMode, OpenMode::OPEN_EXISTING), permissions) + .failureReturnValue(INVALID_HANDLE) + .evaluate(); + if (!result.has_error()) + { + m_handle = result->value; + return true; + } + } + + m_errorValue = errnoToEnum(result.get_error().errnum); return false; } + m_handle = result->value; } - if (m_ownerShip == OwnerShip::MINE) + if (m_hasOwnership) { if (posixCall(ftruncate)(m_handle, static_cast(size)) - .failureReturnValue(-1) + .failureReturnValue(INVALID_HANDLE) .evaluate() - .or_else([this](auto& r) { m_errorValue = this->errnoToEnum(r.errnum); }) + .or_else([this](auto& r) { m_errorValue = errnoToEnum(r.errnum); }) .has_error()) { return false; @@ -176,22 +204,32 @@ bool SharedMemory::open(const int oflags, const mode_t permissions, const uint64 return true; } +cxx::expected SharedMemory::unlinkIfExist(const Name_t& name) noexcept +{ + auto result = + posixCall(iox_shm_unlink)(name.c_str()).failureReturnValue(INVALID_HANDLE).ignoreErrnos(ENOENT).evaluate(); + + if (!result.has_error()) + { + return cxx::success(result->errnum != ENOENT); + } + + return cxx::error(errnoToEnum(result.get_error().errnum)); +} + bool SharedMemory::unlink() noexcept { - if (m_isInitialized && m_ownerShip == OwnerShip::MINE) + if (m_isInitialized && m_hasOwnership) { - if (posixCall(shm_unlink)(m_name.c_str()) - .failureReturnValue(-1) - .evaluate() - .or_else([](auto& r) { - std::cerr << "Unable to unlink SharedMemory (shm_unlink failed) : " << r.getHumanReadableErrnum() - << std::endl; - }) - .has_error()) + auto unlinkResult = unlinkIfExist(m_name); + if (unlinkResult.has_error() || unlinkResult.value() == false) { + std::cerr << "Unable to unlink SharedMemory (shm_unlink failed)." << std::endl; return false; } } + + reset(); return true; } @@ -199,23 +237,23 @@ bool SharedMemory::close() noexcept { if (m_isInitialized) { - auto call = posixCall(iox_close)(m_handle).failureReturnValue(-1).evaluate().or_else([](auto& r) { + auto call = posixCall(iox_close)(m_handle).failureReturnValue(INVALID_HANDLE).evaluate().or_else([](auto& r) { std::cerr << "Unable to close SharedMemory filedescriptor (close failed) : " << r.getHumanReadableErrnum() << std::endl; }); - m_handle = -1; + m_handle = INVALID_HANDLE; return !call.has_error(); } return true; } -SharedMemoryError SharedMemory::errnoToEnum(const int32_t errnum) const noexcept +SharedMemoryError SharedMemory::errnoToEnum(const int32_t errnum) noexcept { switch (errnum) { case EACCES: - std::cerr << "No permission to modify, truncate or to access the shared memory!" << std::endl; + std::cerr << "No permission to modify, truncate or access the shared memory!" << std::endl; return SharedMemoryError::INSUFFICIENT_PERMISSIONS; case EPERM: std::cerr << "Resizing a file beyond its current size is not supported by the filesystem!" << std::endl; diff --git a/iceoryx_hoofs/test/moduletests/test_ipc_channel.cpp b/iceoryx_hoofs/test/moduletests/test_ipc_channel.cpp index 120e9a3027..ba42d86606 100644 --- a/iceoryx_hoofs/test/moduletests/test_ipc_channel.cpp +++ b/iceoryx_hoofs/test/moduletests/test_ipc_channel.cpp @@ -215,6 +215,13 @@ TYPED_TEST(IpcChannel_test, DestroyingServerLeadsToOutdatedClient) EXPECT_TRUE(outdated.value()); } +#if !defined(_WIN32) +// From: +// https://docs.microsoft.com/en-us/windows/win32/memory/sharing-files-and-memory +// The shared memory is not destroyed until every process called CloseHandle on +// that shared memory. If a process as an abnormal termination the kernel calls +// CloseHandle on every open handle, therefore shared memory remains should be +// impossible. TYPED_TEST(IpcChannel_test, UnlinkExistingOneWorks) { auto first = TestFixture::IpcChannelType::create(anotherGoodName, IpcChannelSide::SERVER); @@ -230,6 +237,7 @@ TYPED_TEST(IpcChannel_test, UnlinkNonExistingOneWorks) ASSERT_FALSE(ret.has_error()); EXPECT_FALSE(ret.value()); } +#endif TYPED_TEST(IpcChannel_test, SendAndReceiveWorks) { @@ -342,8 +350,6 @@ TYPED_TEST(IpcChannel_test, TimedSendWorks) "longer message"; Duration maxTimeout = 100_ms; - Duration minTimeoutTolerance = 10_ms; - Duration maxTimeoutTolerance = 20_ms; // send till it breaks for (;;) @@ -356,10 +362,7 @@ TYPED_TEST(IpcChannel_test, TimedSendWorks) ASSERT_THAT(result.get_error(), Eq(IpcChannelError::TIMEOUT)); // Do not exceed timeout auto timeDiff = units::Duration(after - before); - EXPECT_LT(timeDiff, maxTimeout + maxTimeoutTolerance); - - // Check if timedSend has blocked for ~maxTimeout and has not returned immediately - EXPECT_GT(timeDiff, maxTimeout - minTimeoutTolerance); + EXPECT_GT(timeDiff, maxTimeout); break; } @@ -374,8 +377,6 @@ TYPED_TEST(IpcChannel_test, TimedReceiveWorks) std::string msg = "very useful text for tranmission"; Duration timeout = 100_ms; - Duration minTimeoutTolerance = 10_ms; - Duration maxTimeoutTolerance = 20_ms; ASSERT_FALSE(this->client.send(msg).has_error()); @@ -391,11 +392,7 @@ TYPED_TEST(IpcChannel_test, TimedReceiveWorks) ASSERT_TRUE(received.has_error()); ASSERT_THAT(received.get_error(), Eq(IpcChannelError::TIMEOUT)); - // Do not exceed timeout auto timeDiff = units::Duration(after - before); - EXPECT_LT(timeDiff, timeout + maxTimeoutTolerance); - - // Check if timedReceive has blocked for ~timeout and has not returned immediately - EXPECT_GT(timeDiff, timeout - minTimeoutTolerance); + EXPECT_GT(timeDiff, timeout); } } // namespace diff --git a/iceoryx_hoofs/test/moduletests/test_posix_file_lock.cpp b/iceoryx_hoofs/test/moduletests/test_posix_file_lock.cpp index 773b45b3f8..11bf5705e2 100644 --- a/iceoryx_hoofs/test/moduletests/test_posix_file_lock.cpp +++ b/iceoryx_hoofs/test/moduletests/test_posix_file_lock.cpp @@ -14,7 +14,7 @@ // // SPDX-License-Identifier: Apache-2.0 -#if !defined(_WIN32) && !defined(__APPLE__) +#if !defined(__APPLE__) #include "iceoryx_hoofs/cxx/optional.hpp" #include "iceoryx_hoofs/posix_wrapper/file_lock.hpp" #include "test.hpp" @@ -63,15 +63,13 @@ TEST_F(FileLock_test, EmptyNameLeadsToError) { auto sut2 = iox::posix::FileLock::create(""); ASSERT_TRUE(sut2.has_error()); - EXPECT_THAT(sut2.get_error(), Eq(FileLockError::NO_FILE_NAME_PROVIDED)); + EXPECT_THAT(sut2.get_error(), Eq(FileLockError::INVALID_FILE_NAME)); } TEST_F(FileLock_test, MaxStringWorks) { - const FileLock::FileName_t maxString{ - "OeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPalo" - "emaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlancaOeLaPaloemaBlanc" - "aOeLaPaloemaBlancaOeLaPaloemaB"}; + const FileLock::FileName_t maxString(iox::cxx::TruncateToCapacity, + std::string(FileLock::FileName_t().capacity(), 'x')); auto sut2 = iox::posix::FileLock::create(maxString); ASSERT_FALSE(sut2.has_error()); } diff --git a/iceoryx_hoofs/test/moduletests/test_posix_timer.cpp b/iceoryx_hoofs/test/moduletests/test_posix_timer.cpp index 14101ee5d5..9983f35038 100644 --- a/iceoryx_hoofs/test/moduletests/test_posix_timer.cpp +++ b/iceoryx_hoofs/test/moduletests/test_posix_timer.cpp @@ -291,18 +291,19 @@ TIMING_TEST_F(Timer_test, MultipleTimersRunningContinuously, Repeat(5), [&] { ASSERT_FALSE(sut.timer.start(Timer::RunMode::PERIODIC, Timer::CatchUpPolicy::SKIP_TO_NEXT_BEAT).has_error()); } - std::this_thread::sleep_for(std::chrono::milliseconds(10 * TIMEOUT.toMilliseconds())); + constexpr int64_t REPETITIONS = 10; + std::this_thread::sleep_for(std::chrono::milliseconds(REPETITIONS * TIMEOUT.toMilliseconds())); for (auto& sut : sutList) { ASSERT_FALSE(sut.timer.stop().has_error()); } - std::this_thread::sleep_for(std::chrono::milliseconds(10 * TIMEOUT.toMilliseconds())); + std::this_thread::sleep_for(std::chrono::milliseconds(REPETITIONS * TIMEOUT.toMilliseconds())); for (auto& sut : sutList) { - TIMING_TEST_EXPECT_TRUE(7 <= sut.value && sut.value <= 13); + TIMING_TEST_EXPECT_TRUE(REPETITIONS / 2 <= sut.value && sut.value <= 3 * REPETITIONS / 2); } }); diff --git a/iceoryx_hoofs/test/moduletests/test_shared_memory.cpp b/iceoryx_hoofs/test/moduletests/test_shared_memory.cpp index 85662f9b9e..b1b40775f1 100644 --- a/iceoryx_hoofs/test/moduletests/test_shared_memory.cpp +++ b/iceoryx_hoofs/test/moduletests/test_shared_memory.cpp @@ -19,65 +19,85 @@ #include "iceoryx_hoofs/internal/posix_wrapper/shared_memory_object/shared_memory.hpp" #include "iceoryx_hoofs/platform/stat.hpp" +#include "iceoryx_hoofs/posix_wrapper/posix_call.hpp" + +#include namespace { using namespace testing; +using namespace iox; +using namespace iox::posix; class SharedMemory_Test : public Test { public: void SetUp() override { - internal::CaptureStderr(); + testing::internal::CaptureStderr(); + auto result = iox::posix::SharedMemory::unlinkIfExist(SUT_SHM_NAME); + ASSERT_FALSE(result.has_error()); } void TearDown() override { - std::string output = internal::GetCapturedStderr(); + std::string output = testing::internal::GetCapturedStderr(); if (Test::HasFailure()) { std::cout << output << std::endl; } } -}; -TEST_F(SharedMemory_Test, CTorWithValidArguments) -{ - auto sut = iox::posix::SharedMemory::create("/ignatz", + static constexpr const char SUT_SHM_NAME[] = "/ignatz"; + + iox::cxx::expected + createSut(const iox::posix::SharedMemory::Name_t& name, const iox::posix::OpenMode openMode) + { + return iox::posix::SharedMemory::create(name, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + openMode, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, 128); + } + + bool createRawSharedMemory(const iox::posix::SharedMemory::Name_t& name) + { + return !iox::posix::posixCall(iox_shm_open)( + name.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) + .failureReturnValue(SharedMemory::INVALID_HANDLE) + .evaluate() + .has_error(); + } + + bool cleanupSharedMemory(const iox::posix::SharedMemory::Name_t& name) + { + auto result = iox::posix::SharedMemory::unlinkIfExist(name); + if (result.has_error()) + { + EXPECT_TRUE(false); + return false; + } + return *result; + } +}; + +constexpr const char SharedMemory_Test::SUT_SHM_NAME[]; + +TEST_F(SharedMemory_Test, CTorWithValidArguments) +{ + auto sut = createSut(SUT_SHM_NAME, iox::posix::OpenMode::PURGE_AND_CREATE); EXPECT_THAT(sut.has_error(), Eq(false)); } TEST_F(SharedMemory_Test, CTorWithInvalidMessageQueueNames) { - EXPECT_THAT(iox::posix::SharedMemory::create("", - iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, - 128) - .has_error(), - Eq(true)); - - EXPECT_THAT(iox::posix::SharedMemory::create("ignatz", - iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, - 128) - .has_error(), - Eq(true)); + EXPECT_THAT(createSut("", iox::posix::OpenMode::PURGE_AND_CREATE).has_error(), Eq(true)); + EXPECT_THAT(createSut("ignatz", iox::posix::OpenMode::PURGE_AND_CREATE).has_error(), Eq(true)); } TEST_F(SharedMemory_Test, CTorWithInvalidArguments) { - auto sut = iox::posix::SharedMemory::create("/schlomo", - iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::OPEN_EXISTING_SHM, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, - 128); + auto sut = createSut("/schlomo", iox::posix::OpenMode::OPEN_EXISTING); EXPECT_THAT(sut.has_error(), Eq(true)); } @@ -85,11 +105,8 @@ TEST_F(SharedMemory_Test, MoveCTorWithValidValues) { int handle; - auto sut = iox::posix::SharedMemory::create("/ignatz.", - iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, - 128); + auto sut = createSut(SUT_SHM_NAME, iox::posix::OpenMode::PURGE_AND_CREATE); + ASSERT_FALSE(sut.has_error()); handle = sut->getHandle(); { iox::posix::SharedMemory sut2(std::move(*sut)); @@ -100,11 +117,110 @@ TEST_F(SharedMemory_Test, MoveCTorWithValidValues) TEST_F(SharedMemory_Test, getHandleOfValidObject) { - auto sut = iox::posix::SharedMemory::create("/ignatz..", - iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH, - 128); - EXPECT_THAT(sut->getHandle(), Ne(-1)); + auto sut = createSut(SUT_SHM_NAME, iox::posix::OpenMode::PURGE_AND_CREATE); + ASSERT_FALSE(sut.has_error()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); } + +TEST_F(SharedMemory_Test, UnlinkNonExistingShmFails) +{ + auto result = iox::posix::SharedMemory::unlinkIfExist("/look_there's_a_dead_seagull_flying_its_name_is_dietlbart"); + ASSERT_FALSE(result.has_error()); + EXPECT_FALSE(*result); +} + +TEST_F(SharedMemory_Test, UnlinkExistingShmWorks) +{ + constexpr const char SHM_NAME[] = "/its_a_mee_monukulius"; + ASSERT_TRUE(createRawSharedMemory(SHM_NAME)); + auto result = iox::posix::SharedMemory::unlinkIfExist(SHM_NAME); + ASSERT_FALSE(result.has_error()); + EXPECT_TRUE(*result); +} + +TEST_F(SharedMemory_Test, ExclusiveCreateWorksWhenShmDoesNotExist) +{ + IOX_DISCARD_RESULT(iox::posix::SharedMemory::unlinkIfExist(SUT_SHM_NAME)); + { + auto sut = createSut(SUT_SHM_NAME, OpenMode::EXCLUSIVE_CREATE); + ASSERT_FALSE(sut.has_error()); + EXPECT_TRUE(sut->hasOwnership()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); + } + EXPECT_FALSE(cleanupSharedMemory(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, ExclusiveCreateFailsWhenShmExists) +{ + ASSERT_TRUE(createRawSharedMemory(SUT_SHM_NAME)); + auto sut = createSut(SUT_SHM_NAME, OpenMode::EXCLUSIVE_CREATE); + ASSERT_TRUE(sut.has_error()); + IOX_DISCARD_RESULT(iox::posix::SharedMemory::unlinkIfExist(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, PurgeAndCreateWorksWhenShmDoesNotExist) +{ + { + auto sut = createSut(SUT_SHM_NAME, OpenMode::PURGE_AND_CREATE); + ASSERT_FALSE(sut.has_error()); + EXPECT_TRUE(sut->hasOwnership()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); + } + EXPECT_FALSE(cleanupSharedMemory(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, PurgeAndCreateWorksWhenShmExists) +{ + { + ASSERT_TRUE(createRawSharedMemory(SUT_SHM_NAME)); + auto sut = createSut(SUT_SHM_NAME, OpenMode::PURGE_AND_CREATE); + ASSERT_FALSE(sut.has_error()); + EXPECT_TRUE(sut->hasOwnership()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); + } + EXPECT_FALSE(cleanupSharedMemory(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, CreateOrOpenCreatesShmWhenShmDoesNotExist) +{ + { + auto sut = createSut(SUT_SHM_NAME, OpenMode::OPEN_OR_CREATE); + ASSERT_FALSE(sut.has_error()); + EXPECT_TRUE(sut->hasOwnership()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); + } + EXPECT_FALSE(cleanupSharedMemory(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, CreateOrOpenOpensShmWhenShmDoesExist) +{ + ASSERT_TRUE(createRawSharedMemory(SUT_SHM_NAME)); + { + auto sut = createSut(SUT_SHM_NAME, OpenMode::OPEN_OR_CREATE); + ASSERT_FALSE(sut.has_error()); + EXPECT_FALSE(sut->hasOwnership()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); + } + EXPECT_TRUE(cleanupSharedMemory(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, OpenWorksWhenShmExist) +{ + ASSERT_TRUE(createRawSharedMemory(SUT_SHM_NAME)); + { + auto sut = createSut(SUT_SHM_NAME, OpenMode::OPEN_EXISTING); + ASSERT_FALSE(sut.has_error()); + EXPECT_FALSE(sut->hasOwnership()); + EXPECT_THAT(sut->getHandle(), Ne(SharedMemory::INVALID_HANDLE)); + } + EXPECT_TRUE(cleanupSharedMemory(SUT_SHM_NAME)); +} + +TEST_F(SharedMemory_Test, OpenFailsWhenShmDoesNotExist) +{ + auto sut = createSut(SUT_SHM_NAME, OpenMode::OPEN_EXISTING); + ASSERT_TRUE(sut.has_error()); +} + + } // namespace diff --git a/iceoryx_hoofs/test/moduletests/test_shared_memory_object.cpp b/iceoryx_hoofs/test/moduletests/test_shared_memory_object.cpp index 524a5a0d58..8b94ef98d6 100644 --- a/iceoryx_hoofs/test/moduletests/test_shared_memory_object.cpp +++ b/iceoryx_hoofs/test/moduletests/test_shared_memory_object.cpp @@ -56,7 +56,7 @@ TEST_F(SharedMemoryObject_Test, CTorWithValidArguments) auto sut = iox::posix::SharedMemoryObject::create("/validShmMem", 100, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); EXPECT_THAT(sut.has_error(), Eq(false)); } @@ -66,7 +66,7 @@ TEST_F(SharedMemoryObject_Test, CTorOpenNonExistingSharedMemoryObject) auto sut = iox::posix::SharedMemoryObject::create("/pummeluff", 100, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::OPEN_EXISTING_SHM, + iox::posix::OpenMode::OPEN_EXISTING, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); EXPECT_THAT(sut.has_error(), Eq(true)); } @@ -76,7 +76,7 @@ TEST_F(SharedMemoryObject_Test, AllocateMemoryInSharedMemoryAndReadIt) auto sut = iox::posix::SharedMemoryObject::create("/shmAllocate", 16, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); int* test = static_cast(sut->allocate(sizeof(int), 1)); ASSERT_THAT(test, Ne(nullptr)); @@ -89,7 +89,7 @@ TEST_F(SharedMemoryObject_Test, AllocateWholeSharedMemoryWithOneChunk) auto sut = iox::posix::SharedMemoryObject::create("/shmAllocate", 8, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); void* test = sut->allocate(8, 1); @@ -101,7 +101,7 @@ TEST_F(SharedMemoryObject_Test, AllocateWholeSharedMemoryWithMultipleChunks) auto sut = iox::posix::SharedMemoryObject::create("/shmAllocate", 8, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); for (uint64_t i = 0; i < 8; ++i) @@ -117,7 +117,7 @@ TEST_F(SharedMemoryObject_Test, AllocateTooMuchMemoryInSharedMemoryWithOneChunk) auto sut = iox::posix::SharedMemoryObject::create("/shmAllocate", memorySize, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); PerformDeathTest([&] { sut->allocate(cxx::align(memorySize, posix::Allocator::MEMORY_ALIGNMENT) + 1, 1); }); @@ -129,7 +129,7 @@ TEST_F(SharedMemoryObject_Test, AllocateTooMuchSharedMemoryWithMultipleChunks) auto sut = iox::posix::SharedMemoryObject::create("/shmAllocate", memorySize, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); for (uint64_t i = 0; i < cxx::align(memorySize, posix::Allocator::MEMORY_ALIGNMENT); ++i) @@ -146,7 +146,7 @@ TEST_F(SharedMemoryObject_Test, AllocateAfterFinalizeAllocation) auto sut = iox::posix::SharedMemoryObject::create("/shmAllocate", 8, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); sut->finalizeAllocation(); @@ -159,7 +159,7 @@ TEST_F(SharedMemoryObject_Test, OpeningSharedMemoryAndReadMultipleContents) auto shmMemory = iox::posix::SharedMemoryObject::create("/shmSut", memorySize, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); int* test = static_cast(shmMemory->allocate(sizeof(int), 1)); *test = 4557; @@ -169,7 +169,7 @@ TEST_F(SharedMemoryObject_Test, OpeningSharedMemoryAndReadMultipleContents) auto sut = iox::posix::SharedMemoryObject::create("/shmSut", memorySize, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::OPEN_EXISTING_SHM, + iox::posix::OpenMode::OPEN_EXISTING, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT); int* sutValue1 = static_cast(sut->allocate(sizeof(int), 1)); int* sutValue2 = static_cast(sut->allocate(sizeof(int), 1)); diff --git a/iceoryx_posh/include/iceoryx_posh/internal/mepoo/mepoo_segment.inl b/iceoryx_posh/include/iceoryx_posh/internal/mepoo/mepoo_segment.inl index 1035ac7a03..939faf1318 100644 --- a/iceoryx_posh/include/iceoryx_posh/internal/mepoo/mepoo_segment.inl +++ b/iceoryx_posh/include/iceoryx_posh/internal/mepoo/mepoo_segment.inl @@ -76,7 +76,7 @@ inline SharedMemoryObjectType MePooSegment(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)) .and_then([this](auto& sharedMemoryObject) { diff --git a/iceoryx_posh/include/iceoryx_posh/roudi/memory/posix_shm_memory_provider.hpp b/iceoryx_posh/include/iceoryx_posh/roudi/memory/posix_shm_memory_provider.hpp index 4e9754930a..930a93a545 100644 --- a/iceoryx_posh/include/iceoryx_posh/roudi/memory/posix_shm_memory_provider.hpp +++ b/iceoryx_posh/include/iceoryx_posh/roudi/memory/posix_shm_memory_provider.hpp @@ -1,4 +1,5 @@ // Copyright (c) 2020 by Robert Bosch GmbH. All rights reserved. +// Copyright (c) 2021 by Apex.AI Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -37,11 +38,10 @@ class PosixShmMemoryProvider : public MemoryProvider /// @brief Constructs a PosixShmMemoryProvider which can be used to request memory via MemoryBlocks /// @param [in] shmName is the name of the posix share memory /// @param [in] accessMode defines the read and write access to the memory - /// @param [in] ownership defines the ownership of the shared memory. "mine" controls the lifetime of the memory and - /// "openExisting" will just use an already existing shared memory + /// @param [in] openMode defines the creation/open mode of the shared memory. PosixShmMemoryProvider(const ShmName_t& shmName, const posix::AccessMode accessMode, - const posix::OwnerShip ownership) noexcept; + const posix::OpenMode openMode) noexcept; ~PosixShmMemoryProvider() noexcept; PosixShmMemoryProvider(PosixShmMemoryProvider&&) = delete; @@ -65,7 +65,7 @@ class PosixShmMemoryProvider : public MemoryProvider private: ShmName_t m_shmName; posix::AccessMode m_accessMode{posix::AccessMode::READ_ONLY}; - posix::OwnerShip m_ownership{posix::OwnerShip::OPEN_EXISTING_SHM}; + posix::OpenMode m_openMode{posix::OpenMode::OPEN_EXISTING}; cxx::optional m_shmObject; }; diff --git a/iceoryx_posh/source/roudi/memory/default_roudi_memory.cpp b/iceoryx_posh/source/roudi/memory/default_roudi_memory.cpp index fc6b343c83..410e06b797 100644 --- a/iceoryx_posh/source/roudi/memory/default_roudi_memory.cpp +++ b/iceoryx_posh/source/roudi/memory/default_roudi_memory.cpp @@ -27,7 +27,7 @@ namespace roudi DefaultRouDiMemory::DefaultRouDiMemory(const RouDiConfig_t& roudiConfig) noexcept : m_introspectionMemPoolBlock(introspectionMemPoolConfig()) , m_segmentManagerBlock(roudiConfig) - , m_managementShm(SHM_NAME, posix::AccessMode::READ_WRITE, posix::OwnerShip::MINE) + , m_managementShm(SHM_NAME, posix::AccessMode::READ_WRITE, posix::OpenMode::PURGE_AND_CREATE) { m_managementShm.addMemoryBlock(&m_introspectionMemPoolBlock).or_else([](auto) { diff --git a/iceoryx_posh/source/roudi/memory/posix_shm_memory_provider.cpp b/iceoryx_posh/source/roudi/memory/posix_shm_memory_provider.cpp index cbca6f5dc0..1438089ed5 100644 --- a/iceoryx_posh/source/roudi/memory/posix_shm_memory_provider.cpp +++ b/iceoryx_posh/source/roudi/memory/posix_shm_memory_provider.cpp @@ -30,10 +30,10 @@ namespace roudi { PosixShmMemoryProvider::PosixShmMemoryProvider(const ShmName_t& shmName, const posix::AccessMode accessMode, - const posix::OwnerShip ownership) noexcept + const posix::OpenMode openMode) noexcept : m_shmName(shmName) , m_accessMode(accessMode) - , m_ownership(ownership) + , m_openMode(openMode) { } @@ -53,7 +53,7 @@ cxx::expected PosixShmMemoryProvider::createMemory(c return cxx::error(MemoryProviderError::MEMORY_ALIGNMENT_EXCEEDS_PAGE_SIZE); } - posix::SharedMemoryObject::create(m_shmName, size, m_accessMode, m_ownership, nullptr) + posix::SharedMemoryObject::create(m_shmName, size, m_accessMode, m_openMode, nullptr) .and_then([this](auto& sharedMemoryObject) { sharedMemoryObject.finalizeAllocation(); m_shmObject.emplace(std::move(sharedMemoryObject)); diff --git a/iceoryx_posh/source/runtime/shared_memory_user.cpp b/iceoryx_posh/source/runtime/shared_memory_user.cpp index c2e486d425..e72ab293ac 100644 --- a/iceoryx_posh/source/runtime/shared_memory_user.cpp +++ b/iceoryx_posh/source/runtime/shared_memory_user.cpp @@ -34,7 +34,7 @@ SharedMemoryUser::SharedMemoryUser(const size_t topicSize, posix::SharedMemoryObject::create(roudi::SHM_NAME, topicSize, posix::AccessMode::READ_WRITE, - posix::OwnerShip::OPEN_EXISTING_SHM, + posix::OpenMode::OPEN_EXISTING, posix::SharedMemoryObject::NO_ADDRESS_HINT) .and_then([this, segmentId, segmentManagerAddressOffset](auto& sharedMemoryObject) { rp::BaseRelativePointer::registerPtr( @@ -63,7 +63,7 @@ void SharedMemoryUser::openDataSegments(const uint64_t segmentId, posix::SharedMemoryObject::create(segment.m_sharedMemoryName, segment.m_size, accessMode, - posix::OwnerShip::OPEN_EXISTING_SHM, + posix::OpenMode::OPEN_EXISTING, posix::SharedMemoryObject::NO_ADDRESS_HINT) .and_then([this, &segment](auto& sharedMemoryObject) { if (static_cast(m_dataShmObjects.size()) >= MAX_SHM_SEGMENTS) diff --git a/iceoryx_posh/test/integrationtests/test_shm_sigbus_handler.cpp b/iceoryx_posh/test/integrationtests/test_shm_sigbus_handler.cpp index 17fb69bc8e..b0e9693b0c 100644 --- a/iceoryx_posh/test/integrationtests/test_shm_sigbus_handler.cpp +++ b/iceoryx_posh/test/integrationtests/test_shm_sigbus_handler.cpp @@ -31,7 +31,6 @@ using namespace ::testing; TEST(ShmCreatorDeathTest, AllocatingTooMuchMemoryLeadsToExitWithSIGBUS) { const iox::ShmName_t TEST_SHM_NAME{"/test_name"}; - // the death test makes only sense on platforms which are zeroing the whole shared memory // if the memory is only reserved a death will never occur if (iox::platform::IOX_SHM_WRITE_ZEROS_ON_CREATION) @@ -41,7 +40,7 @@ TEST(ShmCreatorDeathTest, AllocatingTooMuchMemoryLeadsToExitWithSIGBUS) badconfig.addMemPool({1 << 30, 100}); iox::roudi::MemPoolCollectionMemoryBlock badmempools(badconfig); iox::roudi::PosixShmMemoryProvider badShmProvider( - TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OwnerShip::MINE); + TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OpenMode::PURGE_AND_CREATE); ASSERT_FALSE(badShmProvider.addMemoryBlock(&badmempools).has_error()); EXPECT_DEATH(IOX_DISCARD_RESULT(badShmProvider.create()), ".*"); @@ -53,7 +52,7 @@ TEST(ShmCreatorDeathTest, AllocatingTooMuchMemoryLeadsToExitWithSIGBUS) goodconfig.addMemPool({1024, 1}); iox::roudi::MemPoolCollectionMemoryBlock goodmempools(goodconfig); iox::roudi::PosixShmMemoryProvider goodShmProvider( - TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OwnerShip::MINE); + TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OpenMode::PURGE_AND_CREATE); ASSERT_FALSE(goodShmProvider.addMemoryBlock(&goodmempools).has_error()); ASSERT_FALSE(goodShmProvider.create().has_error()); } diff --git a/iceoryx_posh/test/moduletests/test_mepoo_segment.cpp b/iceoryx_posh/test/moduletests/test_mepoo_segment.cpp index 65ece4d212..91e58afa15 100644 --- a/iceoryx_posh/test/moduletests/test_mepoo_segment.cpp +++ b/iceoryx_posh/test/moduletests/test_mepoo_segment.cpp @@ -59,13 +59,13 @@ class MePooSegment_test : public Test using createFct = std::function; SharedMemoryObject_MOCK(const SharedMemory::Name_t& name, const uint64_t memorySizeInBytes, const AccessMode accessMode, - const OwnerShip ownerShip, + const OpenMode openMode, const void* baseAddressHint, const mode_t permissions) : m_memorySizeInBytes(memorySizeInBytes) @@ -73,7 +73,7 @@ class MePooSegment_test : public Test { if (createVerificator) { - createVerificator(name, memorySizeInBytes, accessMode, ownerShip, baseAddressHint, permissions); + createVerificator(name, memorySizeInBytes, accessMode, openMode, baseAddressHint, permissions); } filehandle = creat("/tmp/roudi_segment_test", S_IRWXU); m_isInitialized = true; @@ -152,12 +152,12 @@ TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(SharedMemoryCreationPara MePooSegment_test::SharedMemoryObject_MOCK::createVerificator = [](const SharedMemory::Name_t f_name, const uint64_t, const iox::posix::AccessMode f_accessMode, - const iox::posix::OwnerShip f_ownerShip, + const iox::posix::OpenMode openMode, const void*, const mode_t) { EXPECT_THAT(std::string(f_name), Eq(std::string("/iox_roudi_test2"))); EXPECT_THAT(f_accessMode, Eq(iox::posix::AccessMode::READ_WRITE)); - EXPECT_THAT(f_ownerShip, Eq(iox::posix::OwnerShip::MINE)); + EXPECT_THAT(openMode, Eq(iox::posix::OpenMode::PURGE_AND_CREATE)); }; MePooSegment sut2{ mepooConfig, m_managementAllocator, {"iox_roudi_test1"}, {"iox_roudi_test2"}}; @@ -171,7 +171,7 @@ TEST_F(MePooSegment_test, ADD_TEST_WITH_ADDITIONAL_USER(GetSharedMemoryObject)) MePooSegment_test::SharedMemoryObject_MOCK::createVerificator = [&](const SharedMemory::Name_t, const uint64_t f_memorySizeInBytes, const iox::posix::AccessMode, - const iox::posix::OwnerShip, + const iox::posix::OpenMode, const void*, const mode_t) { memorySizeInBytes = f_memorySizeInBytes; diff --git a/iceoryx_posh/test/moduletests/test_roudi_posix_shm_memory_provider.cpp b/iceoryx_posh/test/moduletests/test_roudi_posix_shm_memory_provider.cpp index 4d993cb220..9c36a08428 100644 --- a/iceoryx_posh/test/moduletests/test_roudi_posix_shm_memory_provider.cpp +++ b/iceoryx_posh/test/moduletests/test_roudi_posix_shm_memory_provider.cpp @@ -41,7 +41,7 @@ class PosixShmMemoryProvider_Test : public Test IOX_DISCARD_RESULT(iox::posix::SharedMemoryObject::create(TEST_SHM_NAME, 1024, iox::posix::AccessMode::READ_WRITE, - iox::posix::OwnerShip::MINE, + iox::posix::OpenMode::PURGE_AND_CREATE, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT)); } @@ -54,7 +54,7 @@ class PosixShmMemoryProvider_Test : public Test return !iox::posix::SharedMemoryObject::create(TEST_SHM_NAME, 8, iox::posix::AccessMode::READ_ONLY, - iox::posix::OwnerShip::OPEN_EXISTING_SHM, + iox::posix::OpenMode::OPEN_EXISTING, iox::posix::SharedMemoryObject::NO_ADDRESS_HINT) .has_error(); } @@ -65,7 +65,8 @@ class PosixShmMemoryProvider_Test : public Test TEST_F(PosixShmMemoryProvider_Test, CreateMemory) { - PosixShmMemoryProvider sut(TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OwnerShip::MINE); + PosixShmMemoryProvider sut( + TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OpenMode::PURGE_AND_CREATE); ASSERT_FALSE(sut.addMemoryBlock(&memoryBlock1).has_error()); uint64_t MEMORY_SIZE{16}; uint64_t MEMORY_ALIGNMENT{8}; @@ -81,7 +82,8 @@ TEST_F(PosixShmMemoryProvider_Test, CreateMemory) TEST_F(PosixShmMemoryProvider_Test, DestroyMemory) { - PosixShmMemoryProvider sut(TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OwnerShip::MINE); + PosixShmMemoryProvider sut( + TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OpenMode::PURGE_AND_CREATE); ASSERT_FALSE(sut.addMemoryBlock(&memoryBlock1).has_error()); uint64_t MEMORY_SIZE{16}; uint64_t MEMORY_ALIGNMENT{8}; @@ -99,7 +101,8 @@ TEST_F(PosixShmMemoryProvider_Test, DestroyMemory) TEST_F(PosixShmMemoryProvider_Test, CreationFailedWithAlignmentExceedingPageSize) { - PosixShmMemoryProvider sut(TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OwnerShip::MINE); + PosixShmMemoryProvider sut( + TEST_SHM_NAME, iox::posix::AccessMode::READ_WRITE, iox::posix::OpenMode::PURGE_AND_CREATE); ASSERT_FALSE(sut.addMemoryBlock(&memoryBlock1).has_error()); uint64_t MEMORY_SIZE{16}; uint64_t MEMORY_ALIGNMENT{iox::posix::pageSize() + 8U};