Skip to content

Commit

Permalink
Merge pull request eclipse-iceoryx#598 from ApexAI/iox-#404-extend-ti…
Browse files Browse the repository at this point in the history
…meout-registration-info

Iox eclipse-iceoryx#404 Extend timeout registration info and send termination request on destruction
  • Loading branch information
mossmaurice authored Mar 24, 2021
2 parents aa162c6 + c5b710d commit 438291f
Show file tree
Hide file tree
Showing 27 changed files with 1,314 additions and 1,042 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ def generate_test_description():
sigterm_timeout='20')

return launch.LaunchDescription([
roudi_process,
process_list[0],
process_list[1],
process_list[2],
process_list[3],
process_list[4],
roudi_process,
launch_testing.actions.ReadyToTest()
]), {'iox-ex-waitset-publisher': process_list[0], 'iox-ex-waitset-gateway': process_list[1],
'iox-ex-waitset-grouping': process_list[2], 'iox-ex-waitset-individual': process_list[3],
Expand Down
3 changes: 2 additions & 1 deletion iceoryx_posh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ add_library(iceoryx_posh_roudi
source/roudi/port_pool.cpp
source/roudi/roudi.cpp
source/roudi/roudi_lock.cpp
source/roudi/roudi_process.cpp
source/roudi/process.cpp
source/roudi/process_manager.cpp
source/roudi/service_registry.cpp
source/roudi/iceoryx_roudi_components.cpp
source/roudi/roudi_cmd_line_parser.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#include "iceoryx_posh/internal/log/posh_logging.hpp"
#include "iceoryx_posh/internal/mepoo/memory_manager.hpp"
#include "iceoryx_posh/internal/roudi/port_manager.hpp"
#include "iceoryx_posh/internal/roudi/roudi_process.hpp"
#include "iceoryx_posh/mepoo/mepoo_config.hpp"
#include "iceoryx_posh/roudi/introspection_types.hpp"
#include "iceoryx_utils/cxx/method_callback.hpp"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class PortManager
acquirePublisherPortData(const capro::ServiceDescription& service,
const popo::PublisherOptions& publisherOptions,
const ProcessName_t& processName,
mepoo::MemoryManager* payloadMemoryManager,
mepoo::MemoryManager* const payloadMemoryManager,
const PortConfigInfo& portConfigInfo) noexcept;

cxx::expected<SubscriberPortType::MemberType_t*, PortPoolError>
Expand Down Expand Up @@ -127,8 +127,8 @@ class PortManager
void removeEntryFromServiceRegistry(const capro::IdString_t& service, const capro::IdString_t& instance) noexcept;

template <typename T, std::enable_if_t<std::is_same<T, iox::build::OneToManyPolicy>::value>* = nullptr>
cxx::optional<ProcessName_t>
doesViolateCommunicationPolicy(const capro::ServiceDescription& service) const noexcept;
cxx::optional<ProcessName_t> doesViolateCommunicationPolicy(const capro::ServiceDescription& service) const
noexcept;

template <typename T, std::enable_if_t<std::is_same<T, iox::build::ManyToManyPolicy>::value>* = nullptr>
cxx::optional<ProcessName_t> doesViolateCommunicationPolicy(const capro::ServiceDescription& service
Expand Down
95 changes: 95 additions & 0 deletions iceoryx_posh/include/iceoryx_posh/internal/roudi/process.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) 2019 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.
// 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_POSH_ROUDI_PROCESS_HPP
#define IOX_POSH_ROUDI_PROCESS_HPP

#include "iceoryx_posh/internal/mepoo/segment_manager.hpp"
#include "iceoryx_posh/internal/roudi/introspection/process_introspection.hpp"
#include "iceoryx_posh/internal/roudi/port_manager.hpp"
#include "iceoryx_posh/internal/runtime/ipc_interface_user.hpp"
#include "iceoryx_posh/mepoo/chunk_header.hpp"
#include "iceoryx_posh/version/compatibility_check_level.hpp"
#include "iceoryx_posh/version/version_info.hpp"
#include "iceoryx_utils/cxx/list.hpp"
#include "iceoryx_utils/error_handling/error_handling.hpp"
#include "iceoryx_utils/posix_wrapper/posix_access_rights.hpp"

#include <cstdint>
#include <ctime>

namespace iox
{
namespace roudi
{
class Process
{
public:
/// @brief This class represents an application which has registered at RouDi and manages the communication to the
/// application
/// @param [in] name of the process; this is equal to the IPC channel name, which is used for communication
/// @param [in] pid is the host system process id
/// @param [in] payloadMemoryManager is a pointer to the payload memory manager for this process
/// @param [in] isMonitored indicates if the process should be monitored for being alive
/// @param [in] payloadSegmentId is an identifier for the shm payload segment
/// @param [in] sessionId is an ID generated by RouDi to prevent sending outdated IPC channel transmission
Process(const ProcessName_t& name,
const uint32_t pid,
mepoo::MemoryManager& payloadMemoryManager,
const bool isMonitored,
const uint64_t payloadSegmentId,
const uint64_t sessionId) noexcept;

Process(const Process& other) = delete;
Process& operator=(const Process& other) = delete;
/// @note the move cTor and assignment operator are already implicitly deleted because of the atomic
Process(Process&& other) = delete;
Process& operator=(Process&& other) = delete;
~Process() = default;

uint32_t getPid() const noexcept;

const ProcessName_t getName() const noexcept;

void sendViaIpcChannel(const runtime::IpcMessage& data) noexcept;

/// @brief The session ID which is used to check outdated IPC channel transmissions for this process
/// @return the session ID for this process
uint64_t getSessionId() noexcept;

void setTimestamp(const mepoo::TimePointNs_t timestamp) noexcept;

mepoo::TimePointNs_t getTimestamp() noexcept;

mepoo::MemoryManager& getPayloadMemoryManager() const noexcept;
uint64_t getPayloadSegmentId() const noexcept;

bool isMonitored() const noexcept;

private:
const uint32_t m_pid{0U};
runtime::IpcInterfaceUser m_ipcChannel;
mepoo::TimePointNs_t m_timestamp;
mepoo::MemoryManager& m_payloadMemoryManager;
bool m_isMonitored{true};
uint64_t m_payloadSegmentId{0U};
std::atomic<uint64_t> m_sessionId{0U};
};

} // namespace roudi
} // namespace iox

#endif // IOX_POSH_ROUDI_PROCESS_HPP
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
#ifndef IOX_POSH_ROUDI_ROUDI_PROCESS_HPP
#define IOX_POSH_ROUDI_ROUDI_PROCESS_HPP
#ifndef IOX_POSH_ROUDI_PROCESS_MANAGER_HPP
#define IOX_POSH_ROUDI_PROCESS_MANAGER_HPP

#include "iceoryx_posh/internal/mepoo/segment_manager.hpp"
#include "iceoryx_posh/internal/roudi/introspection/process_introspection.hpp"
#include "iceoryx_posh/internal/roudi/port_manager.hpp"
#include "iceoryx_posh/internal/roudi/process.hpp"
#include "iceoryx_posh/internal/runtime/ipc_interface_user.hpp"
#include "iceoryx_posh/mepoo/chunk_header.hpp"
#include "iceoryx_posh/version/compatibility_check_level.hpp"
Expand All @@ -35,60 +36,6 @@ namespace iox
{
namespace roudi
{
class RouDiProcess
{
public:
/// @brief This class represents an application which has registered at RouDi and manages the communication to the
/// application
/// @param [in] name of the process; this is equal to the IPC channel name, which is used for communication
/// @param [in] pid is the host system process id
/// @param [in] payloadMemoryManager is a pointer to the payload memory manager for this process
/// @param [in] isMonitored indicates if the process should be monitored for being alive
/// @param [in] payloadSegmentId is an identifier for the shm payload segment
/// @param [in] sessionId is an ID generated by RouDi to prevent sending outdated IPC channel transmission
RouDiProcess(const ProcessName_t& name,
int32_t pid,
mepoo::MemoryManager* payloadMemoryManager,
bool isMonitored,
const uint64_t payloadSegmentId,
const uint64_t sessionId) noexcept;

RouDiProcess(const RouDiProcess& other) = delete;
RouDiProcess& operator=(const RouDiProcess& other) = delete;
/// @note the move cTor and assignment operator are already implicitly deleted because of the atomic
RouDiProcess(RouDiProcess&& other) = delete;
RouDiProcess& operator=(RouDiProcess&& other) = delete;
~RouDiProcess() = default;

int32_t getPid() const noexcept;

const ProcessName_t getName() const noexcept;

void sendViaIpcChannel(const runtime::IpcMessage& data) noexcept;

/// @brief The session ID which is used to check outdated IPC channel transmissions for this process
/// @return the session ID for this process
uint64_t getSessionId() noexcept;

void setTimestamp(const mepoo::TimePointNs_t timestamp) noexcept;

mepoo::TimePointNs_t getTimestamp() noexcept;

mepoo::MemoryManager* getPayloadMemoryManager() const noexcept;
uint64_t getPayloadSegmentId() const noexcept;

bool isMonitored() const noexcept;

private:
int m_pid;
runtime::IpcInterfaceUser m_ipcChannel;
mepoo::TimePointNs_t m_timestamp;
mepoo::MemoryManager* m_payloadMemoryManager{nullptr};
bool m_isMonitored{true};
uint64_t m_payloadSegmentId;
std::atomic<uint64_t> m_sessionId;
};

class ProcessManagerInterface
{
public:
Expand All @@ -101,9 +48,15 @@ class ProcessManagerInterface
class ProcessManager : public ProcessManagerInterface
{
public:
using ProcessList_t = cxx::list<RouDiProcess, MAX_PROCESS_NUMBER>;
using ProcessList_t = cxx::list<Process, MAX_PROCESS_NUMBER>;
using PortConfigInfo = iox::runtime::PortConfigInfo;

enum class TerminationFeedback
{
SEND_ACK_TO_PROCESS,
DO_NOT_SEND_ACK_TO_PROCESS
};

ProcessManager(RouDiMemoryInterface& roudiMemoryInterface,
PortManager& portManager,
const version::CompatibilityCheckLevel compatibilityCheckLevel) noexcept;
Expand All @@ -120,20 +73,33 @@ class ProcessManager : public ProcessManagerInterface
/// @param [in] transmissionTimestamp is an ID for the application to check for the expected response
/// @param [in] sessionId is an ID generated by RouDi to prevent sending outdated IPC channel transmission
/// @param [in] versionInfo Version of iceoryx used
/// @return Returns if the process could be added successfully.
/// @return false if process was already registered, true otherwise
bool registerProcess(const ProcessName_t& name,
int32_t pid,
posix::PosixUser user,
bool isMonitored,
int64_t transmissionTimestamp,
const uint32_t pid,
const posix::PosixUser user,
const bool isMonitored,
const int64_t transmissionTimestamp,
const uint64_t sessionId,
const version::VersionInfo& versionInfo) noexcept;

/// @brief Kills all registered processes. First try with a SIGTERM and if they have not terminated after
/// processKillDelay they are killed with SIGKILL. If RouDi doesn't have sufficient rights to kill the process, the
/// @brief Unregisters a process at the ProcessManager
/// @param [in] name of the process which wants to unregister
/// @return true if known process was unregistered, false if process is unknown
bool unregisterProcess(const ProcessName_t& name) noexcept;

/// @brief Kills all registered processes. If RouDi doesn't have sufficient rights to kill the process, the
/// process is considered killed.
/// @param [in] processKillDelay Amount of time RouDi will wait before killing
void killAllProcesses(const units::Duration processKillDelay) noexcept;
void killAllProcesses() noexcept;

/// @brief Informs the user about the processes which are registered and then clears the process list
void printWarningForRegisteredProcessesAndClearProcessList() noexcept;

/// @brief Is one or more of the registered processes running?
/// @return true if one or more of the registered processes is running, false otherwise
bool isAnyRegisteredProcessStillRunning() noexcept;

/// @brief Tries to gracefully terminate all registered processes
void requestShutdownOfAllProcesses() noexcept;

void updateLivelinessOfProcess(const ProcessName_t& name) noexcept;

Expand Down Expand Up @@ -171,7 +137,10 @@ class ProcessManager : public ProcessManagerInterface
void sendServiceRegistryChangeCounterToProcess(const ProcessName_t& process_name) noexcept override;

private:
RouDiProcess* getProcessFromList(const ProcessName_t& name) noexcept;
bool searchForProcessAndThen(const ProcessName_t& name,
cxx::function_ref<void(Process&)> AndThenCallable,
cxx::function_ref<void()> OrElseCallable) noexcept;

void monitorProcesses() noexcept;
void discoveryUpdate() noexcept override;

Expand All @@ -185,26 +154,27 @@ class ProcessManager : public ProcessManagerInterface
/// @param [in] versionInfo Version of iceoryx used
/// @return Returns if the process could be added successfully.
bool addProcess(const ProcessName_t& name,
int32_t pid,
mepoo::MemoryManager* payloadMemoryManager,
bool isMonitored,
int64_t transmissionTimestamp,
const uint32_t pid,
cxx::not_null<mepoo::MemoryManager* const> payloadMemoryManager,
const bool isMonitored,
const int64_t transmissionTimestamp,
const uint64_t payloadSegmentId,
const uint64_t sessionId,
const version::VersionInfo& versionInfo) noexcept;

/// @brief Removes the process from the managed client process list, identified by its id.
/// @param [in] name The process name which should be removed.
/// @param [in] sendAckToProcess Informs process that the termination messsage was received
/// @return Returns true if the process was found and removed from the internal list.
bool removeProcess(const ProcessName_t& name) noexcept;
bool searchForProcessAndRemoveIt(const ProcessName_t& name, const TerminationFeedback feedback) noexcept;

/// @brief Removes the given process from the managed client process list without taking the list's lock!
/// @param [in] lockGuard This method has to be called within a lock guard context. Providing this lock guard
/// ensures it can't be called without a lock guard in place. The lock guard is the one
/// associated with the process list.
/// @brief Removes the given process from the managed client process list and the respective resources in shared
/// memory
/// @param [in] processIter The process which should be removed.
/// @param [in] sendAckToProcess Informs process that the termination messsage was received
/// @return Returns true if the process was found and removed from the internal list.
bool removeProcess(const std::lock_guard<std::mutex>& lockGuard, ProcessList_t::iterator& processIter) noexcept;
bool removeProcessAndDeleteRespectiveSharedMemoryObjects(ProcessList_t::iterator& processIter,
const TerminationFeedback feedback) noexcept;

enum class ShutdownPolicy
{
Expand All @@ -217,20 +187,20 @@ class ProcessManager : public ProcessManagerInterface
/// @param [in] shutdownPolicy Signal passed to the system to shut down the process
/// @param [in] shutdownLog Defines the logging detail.
/// @return Returns true if the sent signal was successful.
bool requestShutdownOfProcess(const RouDiProcess& process, ShutdownPolicy shutdownPolicy) noexcept;
bool requestShutdownOfProcess(Process& process, ShutdownPolicy shutdownPolicy) noexcept;

/// @brief Evaluates with a kill SIGTERM signal to a process if he is still alive.
/// @param [in] process The process to check.
/// @return Returns true if the process is still alive, otherwise false.
bool isProcessAlive(const RouDiProcess& process) noexcept;
bool isProcessAlive(const Process& process) noexcept;

/// @brief Evaluates eventual upcoming errors from kill() command in requestShutdownOfProcess and isProcessAlive.
/// @brief Evaluates eventual upcoming errors from kill() command in requestShutdownOfProcess
/// Calls the errorhandler.
/// @param [in] process process where the kill command was run on
/// @param [in] errnum errorcode of the killcommand
/// @param [in] errorString errorstring of the killcommand
/// @param [in] shutdownPolicy enum which tells what termination command was used (e.g. SIGTERM)
void evaluateKillError(const RouDiProcess& process,
void evaluateKillError(const Process& process,
const int32_t& errnum,
const char* errorString,
ShutdownPolicy shutdownPolicy) noexcept;
Expand All @@ -240,18 +210,14 @@ class ProcessManager : public ProcessManagerInterface
mepoo::SegmentManager<>* m_segmentManager{nullptr};
mepoo::MemoryManager* m_introspectionMemoryManager{nullptr};
RelativePointer::id_t m_mgmtSegmentId{RelativePointer::NULL_POINTER_ID};
mutable std::mutex m_mutex;

ProcessList_t m_processList;

ProcessIntrospectionType* m_processIntrospection{nullptr};

// this is currently used for the internal publisher/subscriber ports
/// @brief is currently used for the internal publisher/subscriber ports
mepoo::MemoryManager* m_memoryManagerOfCurrentProcess{nullptr};
version::CompatibilityCheckLevel m_compatibilityCheckLevel;
};

} // namespace roudi
} // namespace iox

#endif // IOX_POSH_ROUDI_ROUDI_PROCESS_HPP
#endif // IOX_POSH_ROUDI_PROCESS_MANAGER_HPP
Loading

0 comments on commit 438291f

Please sign in to comment.