Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iox #33 implement ipc mutex semaphore #834

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
260ed1b
iox-#33 implemented unique system id as basis for named mutex and sem…
elfenpiff Jun 3, 2021
83bcc59
iox-#33 implemented posix style ipc semaphores in windows
elfenpiff Jun 4, 2021
5af74e1
iox-#33 create ipc handle manager abstraction
elfenpiff Jun 4, 2021
850a621
iox-#33 interprocess capable mutex implemented
elfenpiff Jun 4, 2021
9b8cc39
iox-#33 added windows handle to unix file handle translator
elfenpiff Jun 4, 2021
daaac59
iox-#33 implemented filelock for windows
elfenpiff Jun 4, 2021
2d7c186
iox-#33 activating filelock tests
elfenpiff Jun 4, 2021
82ceea6
iox-#33 file lock file must be a valid file path
elfenpiff Jun 4, 2021
6929a37
iox-#33 reduce the test so that it verifies that only at least the ti…
elfenpiff Jun 4, 2021
ad1dd82
iox-#33 shm unlink impossible/unnessary in windows
elfenpiff Jun 7, 2021
160791b
iox-#33 removed implicit shm removal from posix wrapper and packed it…
elfenpiff Jun 7, 2021
0cee171
iox-#33 added shared memory tests
elfenpiff Jun 7, 2021
f9d9b3e
iox-#33 ipc channel works with windows and named pipes
elfenpiff Jun 7, 2021
9808911
iox-#33 adjusted platform settings variable namespace
elfenpiff Jun 9, 2021
01cf307
iox-#33 handle translator const correctness, adjusted ipc mutex name
elfenpiff Jun 9, 2021
c2b395e
iox-#33 Fix Windows handle_t Issue In HandleTranslator
elfenpiff Jun 9, 2021
890c043
iox-#33 Fix review findings
elfenpiff Jun 10, 2021
a72b44d
iox-#33 Use new policy instead of ownership enum
elfenpiff Jun 10, 2021
8271dfa
iox-#33 Adjust ownership handling
elfenpiff Jun 11, 2021
bcc51d9
iox-#33 Fix review findings
elfenpiff Jun 14, 2021
dad28d5
iox-#33 Fix unused warning for gcc
elfenpiff Jun 14, 2021
c72bb80
iox-#33 Fix shared memory moduletest
elfenpiff Jun 14, 2021
cf67c17
iox-#33 Add platform setting for max shm name length
elfenpiff Jun 14, 2021
6b1d6aa
iox-#33 Try to select right header for mac os SHM_NAME_MAX
elfenpiff Jun 14, 2021
a4588d9
iox-#33 Use MAX_SHM_NAME_LENGTH value from windows in mac
elfenpiff Jun 14, 2021
49f9a0e
iox-#33 Increase SIGBUS_ERROR_MESSAGE_LENGTH
elfenpiff Jun 14, 2021
2c4647a
iox-#33 Introduce iox_shm_unlink
elfenpiff Jun 14, 2021
8de03e1
iox-#33 Add missing mac os errno header
elfenpiff Jun 14, 2021
46d651f
iox-#33 Address review findings
elfenpiff Jun 15, 2021
f2940dd
iox-#33 Fix Timer timing test
elfenpiff Jun 15, 2021
2c301e0
iox-#33 Cleanup shared memory test
elfenpiff Jun 15, 2021
22f6dd4
iox-#33 Add copyright header, consistent variable naming
elfenpiff Jun 16, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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*"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class SharedMemoryObject : public DesignPattern::Creation<SharedMemoryObject, Sh
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 = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,20 @@ enum class AccessMode : uint64_t
};
static constexpr const char* ACCESS_MODE_STRING[] = {"AccessMode::READ_ONLY", "AccessMode::READ_WRITE"};

enum class OwnerShip : uint64_t
/// @brief describes how the shared memory is opened or created
enum class OpenMode : uint64_t
{
MINE = 0U,
OPEN_EXISTING_SHM = 1U
/// @brief creates the shared memory, if it exists already the construction will fail
EXCLUSIVE_CREATE = 0U,
/// @brief creates the shared memory, if it exists it will be deleted and recreated
PURGE_AND_CREATE = 1U,
/// @brief creates the shared memory, if it does not exist otherwise it opens it
OPEN_OR_CREATE = 2U,
/// @brief opens the shared memory, if it does not exist it will fail
OPEN_EXISTING = 3U
};
static constexpr const char* OWNERSHIP_STRING[] = {"OwnerShip::MINE", "OwnerShip::OPEN_EXISTING_SHM"};
static constexpr const char* OPEN_MODE_STRING[] = {
"OpenMode::EXCLUSIVE_CREATE", "OpenMode::PURGE_AND_CREATE", "OpenMode::OPEN_OR_CREATE", "OpenMode::OPEN_EXISTING"};

enum class SharedMemoryError
{
Expand All @@ -63,10 +71,15 @@ enum class SharedMemoryError
UNKNOWN_ERROR
};

/// @brief Creates a bare metal shared memory object with the posix functions
/// shm_open, shm_unlink etc.
/// It must be used in combination with MemoryMap (or manual mmap calls)
// to gain access to the created/opened shared memory
class SharedMemory : public DesignPattern::Creation<SharedMemory, SharedMemoryError>
{
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<NAME_SIZE>;

SharedMemory(const SharedMemory&) = delete;
Expand All @@ -75,29 +88,50 @@ class SharedMemory : public DesignPattern::Creation<SharedMemory, SharedMemoryEr
SharedMemory& operator=(SharedMemory&&) noexcept;
~SharedMemory() noexcept;

/// @brief returns the file handle of the shared memory
int32_t getHandle() const noexcept;

/// @brief this class has the ownership of the shared memory when the shared
/// memory was created by this class. This is the case when this class
/// was successful created with EXCLUSIVE_CREATE, PURGE_AND_CREATE or OPEN_OR_CREATE
/// and the shared memory was created. If an already available shared memory
/// is opened then this class does not have the ownership.
bool hasOwnership() const noexcept;

/// @brief removes shared memory with a given name from the system
/// @param[in] name name of the shared memory
/// @return true if the shared memory was removed, false if the shared memory did not exist and
/// SharedMemoryError when the underlying shm_unlink call failed.
static cxx::expected<bool, SharedMemoryError> unlinkIfExist(const Name_t& name) noexcept;

friend class DesignPattern::Creation<SharedMemory, SharedMemoryError>;

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
Expand Down
20 changes: 8 additions & 12 deletions iceoryx_hoofs/include/iceoryx_hoofs/posix_wrapper/file_lock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -72,8 +63,13 @@ class FileLock : public DesignPattern::Creation<FileLock, FileLockError>
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<FILENAME_LENGTH>;
using PathName_t = cxx::string<platform::IOX_MAX_PATH_LENGTH>;

FileLock(const FileLock&) = delete;
FileLock& operator=(const FileLock&) = delete;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
#include <sys/mman.h>

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
#endif // IOX_HOOFS_LINUX_PLATFORM_MMAN_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define IOX_HOOFS_LINUX_PLATFORM_PLATFORM_SETTINGS_HPP

#include <cstdint>
#include <linux/limits.h>

namespace iox
{
Expand All @@ -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
5 changes: 5 additions & 0 deletions iceoryx_hoofs/platform/linux/source/mman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
#include <sys/mman.h>

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
#endif // IOX_HOOFS_MAC_PLATFORM_MMAN_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions iceoryx_hoofs/platform/mac/source/mman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,24 @@

#include "iceoryx_hoofs/platform/mman.hpp"

#include <errno.h>
#include <sys/shm.h>

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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
#include <sys/mman.h>

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
#endif // IOX_HOOFS_QNX_PLATFORM_MMAN_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions iceoryx_hoofs/platform/qnx/source/mman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
@@ -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 <vector>

/// @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
elfenpiff marked this conversation as resolved.
Show resolved Hide resolved
{
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<HANDLE> m_handleList;
};

#endif
Original file line number Diff line number Diff line change
@@ -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 <map>


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<UniqueSystemId, IpcHandle_t> ipcHandles;
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@
#undef interface
#undef CreateSemaphore
#undef NO_ERROR
#undef OPEN_EXISTING
Loading