Skip to content

Commit

Permalink
Merge pull request #2191 from elBoberido/iox-2185-use-prefix-for-iceo…
Browse files Browse the repository at this point in the history
…ryx-resources

iox-#2185 Use prefix for iceoryx resources
  • Loading branch information
elBoberido authored Feb 21, 2024
2 parents b2e4137 + 473c683 commit 1979ead
Show file tree
Hide file tree
Showing 28 changed files with 310 additions and 97 deletions.
4 changes: 3 additions & 1 deletion doc/website/release-notes/iceoryx-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
- Add support for `iox::string` in `UnixDomainSocket` and created `unix_domain_socket.inl` [#2040](https://github.com/eclipse-iceoryx/iceoryx/issues/2040)
- Add support for `iox::string` in `MessageQueue` and created `message_queue.inl` [#1963](https://github.com/eclipse-iceoryx/iceoryx/issues/1963)
- Add support for `iox::string` in `NamedPipe` and created `named_pipe.inl` [#1693](https://github.com/eclipse-iceoryx/iceoryx/issues/1693)

- Add an `iox1` prefix to all resources created by `iceoryx_posh` and `RouDi` [#2185](https://github.com/eclipse-iceoryx/iceoryx/issues/2185)

**Bugfixes:**

Expand Down Expand Up @@ -119,6 +119,7 @@
- Unable to acquire file status due to an unknown failure [#2023](https://github.com/eclipse-iceoryx/iceoryx/issues/2023)
- Bug in `ListenerImpl` [#2137](https://github.com/eclipse-iceoryx/iceoryx/issues/2137)
- Wrong memory order in `MpmcLoFFLi` fence synchronization [#2196](https://github.com/eclipse-iceoryx/iceoryx/issues/2196)
- Race condition in `PoshRuntime` during shutdown [#2192](https://github.com/eclipse-iceoryx/iceoryx/issues/2192)

**Refactoring:**

Expand Down Expand Up @@ -201,6 +202,7 @@
- Setting IOX_NO_DISCARD in QNX [#638](https://github.com/eclipse-iceoryx/iceoryx/issues/638)
- Replace `iox::byte_t` with std::byte [#1900](https://github.com/eclipse-iceoryx/iceoryx/issues/1900)
- Merge `iceoryx_dust` back to `iceoryx_hoofs` [#2130](https://github.com/eclipse-iceoryx/iceoryx/issues/2130)
- Activate clang-tidy for all the code in iceoryx_hoofs [#2184](https://github.com/eclipse-iceoryx/iceoryx/issues/2184)

**Workflow:**

Expand Down
8 changes: 6 additions & 2 deletions iceoryx_binding_c/test/moduletests/test_runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,18 @@ TEST_F(BindingC_Runtime_test, SuccessfulRegistration)
TEST_F(BindingC_Runtime_test, RuntimeNameLengthIsMax)
{
::testing::Test::RecordProperty("TEST_ID", "854a471d-936e-4c98-b56e-ba8a7d83460e");
std::string maxName(iox::MAX_RUNTIME_NAME_LENGTH, 's');

RuntimeName_t dummy{"a"};
auto prefixLength =
runtime::ipcChannelNameToInterfaceName(dummy, ResourceType::USER_DEFINED).value().size() - dummy.size();
std::string maxName(iox::MAX_RUNTIME_NAME_LENGTH - prefixLength, 's');

iox_runtime_init(maxName.c_str());

char actualRuntimeName[iox::MAX_RUNTIME_NAME_LENGTH + 1];
auto nameLength = iox_runtime_get_instance_name(actualRuntimeName, iox::MAX_RUNTIME_NAME_LENGTH + 1);

ASSERT_THAT(nameLength, Eq(iox::MAX_RUNTIME_NAME_LENGTH));
ASSERT_THAT(nameLength, Eq(iox::MAX_RUNTIME_NAME_LENGTH - prefixLength));
}

TEST_F(BindingC_Runtime_test, RuntimeNameLengthIsOutOfLimit)
Expand Down
22 changes: 20 additions & 2 deletions iceoryx_posh/include/iceoryx_posh/iceoryx_posh_types.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) 2019 - 2020 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2020 - 2022 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2022 by NXP. All rights reserved.
// Copyright (c) 2024 by Mathias Kraus <[email protected]>. 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.
Expand All @@ -20,6 +21,7 @@

#include "iceoryx_platform/platform_settings.hpp"
#include "iceoryx_posh/iceoryx_posh_deployment.hpp"
#include "iox/detail/convert.hpp"
#include "iox/duration.hpp"
#include "iox/function.hpp"
#include "iox/log/logstream.hpp"
Expand Down Expand Up @@ -196,6 +198,22 @@ struct DefaultChunkQueueConfig
static constexpr uint64_t MAX_QUEUE_CAPACITY = MAX_SUBSCRIBER_QUEUE_CAPACITY;
};

constexpr const char ICEORYX_RESOURCE_PREFIX[] = "iox1";

/// @brief The resource type is used to customize the resource prefix by adding an 'i' or 'u' depending whether the
/// resource is defined by iceoryx, e.g. the roudi IPC channel, or by the user, e.g. the runtime name. This shall
/// prevent the system from being affected by users defining resource names which are intended to be used by iceoryx.
enum class ResourceType
{
ICEORYX_DEFINED,
USER_DEFINED,
};

using ResourcePrefix_t = string<13>; // 'iox1_' + MAX_UINT16_SIZE + '_' + optional 'x_'
/// @brief Returns the prefix string used for resources
/// @param[in] uniqueRouDiID to use for the prefix string
inline ResourcePrefix_t iceoryxResourcePrefix(uint16_t uniqueRouDiID, ResourceType resourceType);

// alias for string
using RuntimeName_t = string<MAX_RUNTIME_NAME_LENGTH>;
using NodeName_t = string<build::IOX_MAX_NODE_NAME_LENGTH>;
Expand All @@ -214,11 +232,11 @@ namespace roudi
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers)
using ConfigFilePathString_t = string<1024>;

constexpr const char ROUDI_LOCK_NAME[] = "iox-unique-roudi";
constexpr const char ROUDI_LOCK_NAME[] = "unique_roudi";
constexpr const char IPC_CHANNEL_ROUDI_NAME[] = "roudi";

/// shared memory segment for the iceoryx management data
constexpr const char SHM_NAME[] = "iceoryx_mgmt";
constexpr const char SHM_NAME[] = "management";

// this is used by the UniquePortId
constexpr uint16_t DEFAULT_UNIQUE_ROUDI_ID{0U};
Expand Down
14 changes: 14 additions & 0 deletions iceoryx_posh/include/iceoryx_posh/iceoryx_posh_types.inl
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright (c) 2020 - 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2024 by Mathias Kraus <[email protected]>. 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.
Expand Down Expand Up @@ -49,6 +50,19 @@ log::LogStream& operator<<(log::LogStream& stream, ConnectionState value) noexce
return stream;
}

ResourcePrefix_t iceoryxResourcePrefix(uint16_t uniqueRouDiID, ResourceType resourceType)
{
static_assert(std::is_same_v<uint16_t, std::remove_const_t<decltype(uniqueRouDiID)>>,
"Please adjust 'MAX_UINT16_WIDTH' to the new fixed width type to have enough space for the "
"stringified unique RouDi ID");
constexpr auto MAX_UINT16_WIDTH{5};
iox::string<MAX_UINT16_WIDTH> uniqueRoudiIdString{TruncateToCapacity,
iox::convert::toString(uniqueRouDiID).c_str()};

auto resourceTypeString{resourceType == ResourceType::ICEORYX_DEFINED ? iox::string<1>{"i"} : iox::string<1>{"u"}};
return concatenate(ICEORYX_RESOURCE_PREFIX, "_", uniqueRoudiIdString, "_", resourceTypeString, "_");
}

namespace roudi
{
inline iox::log::LogStream& operator<<(iox::log::LogStream& logstream, const MonitoringMode& mode) noexcept
Expand Down
19 changes: 17 additions & 2 deletions iceoryx_posh/include/iceoryx_posh/internal/mepoo/mepoo_segment.inl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2023 by Mathias Kraus <[email protected]>. All rights reserved.
// Copyright (c) 2023 - 2024 by Mathias Kraus <[email protected]>. 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.
Expand All @@ -23,6 +23,7 @@
#include "iceoryx_posh/mepoo/memory_info.hpp"
#include "iceoryx_posh/mepoo/mepoo_config.hpp"
#include "iox/bump_allocator.hpp"
#include "iox/detail/convert.hpp"
#include "iox/logging.hpp"
#include "iox/relative_pointer.hpp"

Expand Down Expand Up @@ -72,7 +73,21 @@ inline SharedMemoryObjectType MePooSegment<SharedMemoryObjectType, MemoryManager
{
return std::move(
typename SharedMemoryObjectType::Builder()
.name(writerGroup.getName())
.name([&writerGroup] {
using ShmName_t = detail::PosixSharedMemory::Name_t;
ShmName_t shmName = iceoryxResourcePrefix(roudi::DEFAULT_UNIQUE_ROUDI_ID, ResourceType::USER_DEFINED);
if (shmName.size() + writerGroup.getName().size() > ShmName_t::capacity())
{
IOX_LOG(FATAL,
"The payload segment with the name '"
<< writerGroup.getName().size()
<< "' would exceed the maximum allowed size when used with the '" << shmName
<< "' prefix!");
IOX_PANIC("");
}
shmName.append(TruncateToCapacity, writerGroup.getName());
return shmName;
}())
.memorySizeInBytes(MemoryManager::requiredChunkMemorySize(mempoolConfig))
.accessMode(AccessMode::READ_WRITE)
.openMode(OpenMode::PURGE_AND_CREATE)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ IpcMessageErrorType stringToIpcMessageErrorType(const char* str) noexcept;
/// @param[in] msg enum value to convert
std::string IpcMessageErrorTypeToString(const IpcMessageErrorType msg) noexcept;

/// @brief Transforms an IPC channel name to a prefixed interface name
/// @param[in] channelName the name of the channel without the 'iox1_#_' prefix
/// @param[in] resourceType to be used for the resource prefix
/// @return the interface name with the 'iox1_#_' prefix or a 'nullopt' if the resulting name would be too long
iox::optional<RuntimeName_t> ipcChannelNameToInterfaceName(RuntimeName_t channelName, ResourceType resourceType);

class IpcInterfaceUser;
class IpcInterfaceCreator;

Expand Down Expand Up @@ -231,7 +237,10 @@ class IpcInterface
/// IPC channel needs a unique string to be identified with.
IpcInterface() = delete;

IpcInterface(const RuntimeName_t& runtimeName, const uint64_t maxMessages, const uint64_t messageSize) noexcept;
IpcInterface(const RuntimeName_t& runtimeName,
const ResourceType resourceType,
const uint64_t maxMessages,
const uint64_t messageSize) noexcept;

/// @brief delete copy and move ctor and assignment since they are not needed
IpcInterface(const IpcInterface&) = delete;
Expand Down Expand Up @@ -263,6 +272,7 @@ class IpcInterface
bool hasClosableIpcChannel() const noexcept;

protected:
RuntimeName_t m_interfaceName;
RuntimeName_t m_runtimeName;
uint64_t m_maxMessageSize{0U};
uint64_t m_maxMessages{0U};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ class IpcInterfaceCreator : public IpcInterfaceBase
/// If it fails isInitialized will return false. Therefore, isInitialized
/// should always be called before using this class.
/// @param[in] name Unique identifier of the IPC channel
/// @param[in] resourceType to be used for the resource prefix
/// @param[in] maxMessages maximum number of queued messages
/// @param[in] message size maximum message size
IpcInterfaceCreator(const RuntimeName_t& name,
const ResourceType resourceType,
const uint64_t maxMessages = ROUDI_MAX_MESSAGES,
const uint64_t messageSize = ROUDI_MESSAGE_SIZE) noexcept;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ class IpcInterfaceUser : public IpcInterfaceBase
/// Therefore, isInitialized should always be called
/// before using this class.
/// @param[in] name Unique identifier of the IPC channel
/// @param[in] resourceType to be used for the resource prefix
/// @param[in] maxMessages maximum number of queued messages
/// @param[in] message size maximum message size
IpcInterfaceUser(const RuntimeName_t& name,
const ResourceType resourceType,
const uint64_t maxMessages = APP_MAX_MESSAGES,
const uint64_t messageSize = APP_MESSAGE_SIZE) noexcept;

Expand All @@ -52,4 +54,4 @@ class IpcInterfaceUser : public IpcInterfaceBase
} // namespace runtime
} // namespace iox

#endif // IOX_POSH_RUNTIME_IPC_INTERFACE_USER_HPP
#endif // IOX_POSH_RUNTIME_IPC_INTERFACE_USER_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
#include "iceoryx_posh/runtime/posh_runtime.hpp"
#include "iox/detail/periodic_task.hpp"
#include "iox/function.hpp"
#include "iox/mutex.hpp"
#include "iox/optional.hpp"
#include "iox/smart_lock.hpp"

namespace iox
{
Expand Down Expand Up @@ -109,9 +109,7 @@ class PoshRuntimeImpl : public PoshRuntime
expected<std::tuple<segment_id_underlying_t, UntypedRelativePointer::offset_t>, IpcMessageErrorType>
convert_id_and_offset(IpcMessage& msg);

mutable optional<mutex> m_appIpcRequestMutex;

IpcRuntimeInterface m_ipcChannelInterface;
concurrent::smart_lock<IpcRuntimeInterface> m_ipcChannelInterface;
optional<SharedMemoryUser> m_ShmInterface;

optional<Heartbeat*> m_heartbeat;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,24 +62,7 @@ class IceOryxRouDiMemoryManager : public RouDiMemoryInterface
private:
// in order to prevent a second RouDi to cleanup the memory resources of a running RouDi, this resources are
// protected by a file lock
FileLock fileLock =
std::move(FileLockBuilder()
.name(ROUDI_LOCK_NAME)
.permission(iox::perms::owner_read | iox::perms::owner_write)
.create()
.or_else([](auto& error) {
if (error == FileLockError::LOCKED_BY_OTHER_PROCESS)
{
IOX_LOG(FATAL, "Could not acquire lock, is RouDi still running?");
IOX_REPORT_FATAL(PoshError::ICEORYX_ROUDI_MEMORY_MANAGER__ROUDI_STILL_RUNNING);
}
else
{
IOX_LOG(FATAL, "Error occurred while acquiring file lock named " << ROUDI_LOCK_NAME);
IOX_REPORT_FATAL(PoshError::ICEORYX_ROUDI_MEMORY_MANAGER__COULD_NOT_ACQUIRE_FILE_LOCK);
}
})
.value());
FileLock m_fileLock;

PortPoolMemoryBlock m_portPoolBlock;
optional<PortPool> m_portPool;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,26 @@ namespace iox
namespace roudi
{
IceOryxRouDiMemoryManager::IceOryxRouDiMemoryManager(const RouDiConfig_t& roudiConfig) noexcept
: m_defaultMemory(roudiConfig)
: m_fileLock(
std::move(FileLockBuilder()
.name(concatenate(iceoryxResourcePrefix(DEFAULT_UNIQUE_ROUDI_ID, ResourceType::ICEORYX_DEFINED),
ROUDI_LOCK_NAME))
.permission(iox::perms::owner_read | iox::perms::owner_write)
.create()
.or_else([](auto& error) {
if (error == FileLockError::LOCKED_BY_OTHER_PROCESS)
{
IOX_LOG(FATAL, "Could not acquire lock, is RouDi still running?");
IOX_REPORT_FATAL(PoshError::ICEORYX_ROUDI_MEMORY_MANAGER__ROUDI_STILL_RUNNING);
}
else
{
IOX_LOG(FATAL, "Error occurred while acquiring file lock named " << ROUDI_LOCK_NAME);
IOX_REPORT_FATAL(PoshError::ICEORYX_ROUDI_MEMORY_MANAGER__COULD_NOT_ACQUIRE_FILE_LOCK);
}
})
.value()))
, m_defaultMemory(roudiConfig)
{
m_defaultMemory.m_managementShm.addMemoryBlock(&m_portPoolBlock).or_else([](auto) {
IOX_REPORT_FATAL(PoshError::ICEORYX_ROUDI_MEMORY_MANAGER__FAILED_TO_ADD_PORTPOOL_MEMORY_BLOCK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

#include "iceoryx_posh/roudi/memory/posix_shm_memory_provider.hpp"

#include "iceoryx_posh/iceoryx_posh_types.hpp"
#include "iox/detail/convert.hpp"
#include "iox/detail/system_configuration.hpp"
#include "iox/logging.hpp"

Expand Down Expand Up @@ -55,7 +57,8 @@ expected<void*, MemoryProviderError> PosixShmMemoryProvider::createMemory(const
}

if (!PosixSharedMemoryObjectBuilder()
.name(m_shmName)
.name(
concatenate(iceoryxResourcePrefix(DEFAULT_UNIQUE_ROUDI_ID, ResourceType::ICEORYX_DEFINED), m_shmName))
.memorySizeInBytes(size)
.accessMode(m_accessMode)
.openMode(m_openMode)
Expand Down
2 changes: 1 addition & 1 deletion iceoryx_posh/source/roudi/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Process::Process(const RuntimeName_t& name,
const HeartbeatPoolIndexType heartbeatPoolIndex,
const uint64_t sessionId) noexcept
: m_pid(pid)
, m_ipcChannel(name)
, m_ipcChannel(name, ResourceType::USER_DEFINED)
, m_heartbeatPoolIndex(heartbeatPoolIndex)
, m_user(user)
, m_sessionId(sessionId)
Expand Down
21 changes: 19 additions & 2 deletions iceoryx_posh/source/roudi/roudi.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2019, 2021 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2023 by Mathias Kraus <[email protected]>. All rights reserved.
// Copyright (c) 2023 - 2024 by Mathias Kraus <[email protected]>. 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.
Expand Down Expand Up @@ -248,7 +248,7 @@ void RouDi::processRuntimeMessages() noexcept
{
setThreadName("IPC-msg-process");

runtime::IpcInterfaceCreator roudiIpcInterface{IPC_CHANNEL_ROUDI_NAME};
runtime::IpcInterfaceCreator roudiIpcInterface{IPC_CHANNEL_ROUDI_NAME, ResourceType::ICEORYX_DEFINED};

IOX_LOG(INFO, "RouDi is ready for clients");
fflush(stdout); // explicitly flush 'stdout' for 'launch_testing'
Expand Down Expand Up @@ -289,6 +289,23 @@ void RouDi::processMessage(const runtime::IpcMessage& message,
const iox::runtime::IpcMessageType& cmd,
const RuntimeName_t& runtimeName) noexcept
{
if (runtimeName.empty())
{
IOX_LOG(ERROR, "Got message with empty runtime name!");
return;
}


for (const auto s : platform::IOX_PATH_SEPARATORS)
{
const char separator[2]{s};
if (runtimeName.find(separator).has_value())
{
IOX_LOG(ERROR, "Got message with a runtime name with invalid characters: \"" << runtimeName << "\"!");
return;
}
}

switch (cmd)
{
case runtime::IpcMessageType::REG:
Expand Down
Loading

0 comments on commit 1979ead

Please sign in to comment.