Skip to content

Commit

Permalink
Merge pull request #529 from elfenpiff/iox2-528-make-signal-registrat…
Browse files Browse the repository at this point in the history
…ion-optional

[#528] make signal registration optional
  • Loading branch information
elfenpiff authored Nov 27, 2024
2 parents 521f7cf + b614123 commit 11a446f
Show file tree
Hide file tree
Showing 22 changed files with 474 additions and 41 deletions.
1 change: 1 addition & 0 deletions doc/release-notes/iceoryx2-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Support for slices in the C++ bindings [#490](https://github.com/eclipse-iceoryx/iceoryx2/issues/490)
* Add API to retrieve string description of error enums [$491](https://github.com/eclipse-iceoryx/iceoryx2/issues/491)
* Add relocatable `SlotMap` [#504](https://github.com/eclipse-iceoryx/iceoryx2/issues/504)
* Make signal handling optional in `WaitSet` and `Node` [#528](https://github.com/eclipse-iceoryx/iceoryx2/issues/528)

### Bugfixes

Expand Down
27 changes: 27 additions & 0 deletions iceoryx2-ffi/cxx/include/iox2/enum_translation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "iox2/service_builder_publish_subscribe_error.hpp"
#include "iox2/service_error_enums.hpp"
#include "iox2/service_type.hpp"
#include "iox2/signal_handling_mode.hpp"
#include "iox2/subscriber_error.hpp"
#include "iox2/type_variant.hpp"
#include "iox2/unable_to_deliver_strategy.hpp"
Expand Down Expand Up @@ -1432,6 +1433,32 @@ inline auto from<iox2::WaitSetRunError, const char*>(const iox2::WaitSetRunError
return iox2_waitset_run_error_string(iox::into<iox2_waitset_run_error_e>(value));
}

template <>
constexpr auto from<iox2::SignalHandlingMode, iox2_signal_handling_mode_e>(
const iox2::SignalHandlingMode value) noexcept -> iox2_signal_handling_mode_e {
switch (value) {
case iox2::SignalHandlingMode::Disabled:
return iox2_signal_handling_mode_e_DISABLED;
case iox2::SignalHandlingMode::HandleTerminationRequests:
return iox2_signal_handling_mode_e_HANDLE_TERMINATION_REQUESTS;
}

IOX_UNREACHABLE();
}

template <>
constexpr auto from<int, iox2::SignalHandlingMode>(const int value) noexcept -> iox2::SignalHandlingMode {
const auto variant = static_cast<iox2_signal_handling_mode_e>(value);

switch (variant) {
case iox2_signal_handling_mode_e_DISABLED:
return iox2::SignalHandlingMode::Disabled;
case iox2_signal_handling_mode_e_HANDLE_TERMINATION_REQUESTS:
return iox2::SignalHandlingMode::HandleTerminationRequests;
}

IOX_UNREACHABLE();
}
} // namespace iox

#endif
8 changes: 8 additions & 0 deletions iceoryx2-ffi/cxx/include/iox2/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "iox2/service_builder.hpp"
#include "iox2/service_name.hpp"
#include "iox2/service_type.hpp"
#include "iox2/signal_handling_mode.hpp"

namespace iox2 {
/// The central entry point of iceoryx2. Represents a node of the iceoryx2
Expand Down Expand Up @@ -64,6 +65,9 @@ class Node {
static auto list(ConfigView config, const iox::function<CallbackProgression(NodeState<T>)>& callback)
-> iox::expected<void, NodeListFailure>;

/// Returns the [`SignalHandlingMode`] with which the [`Node`] was created.
auto signal_handling_mode() const -> SignalHandlingMode;

private:
explicit Node(iox2_node_h handle);
void drop();
Expand All @@ -84,6 +88,10 @@ class NodeBuilder {
/// is specified the [`Config::global_config()`] is used.
IOX_BUILDER_OPTIONAL(Config, config);

/// Defines the [`SignalHandlingMode`] for the [`Node`]. It affects the [`Node::wait()`] call
/// that returns any received signal via its [`NodeWaitFailure`]
IOX_BUILDER_OPTIONAL(SignalHandlingMode, signal_handling_mode);

public:
NodeBuilder();
NodeBuilder(NodeBuilder&&) = default;
Expand Down
30 changes: 30 additions & 0 deletions iceoryx2-ffi/cxx/include/iox2/signal_handling_mode.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) 2024 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

#ifndef IOX2_SIGNAL_HANDLING_MODE_HPP
#define IOX2_SIGNAL_HANDLING_MODE_HPP

#include <cstdint>

namespace iox2 {
/// Defines how signals are handled by constructs that might register a custom
/// [`SignalHandler`]
enum class SignalHandlingMode : uint8_t {
/// The signals `SIGINT` and `SIGTERM` are registered and handled. If such a Signal is received
/// the user will be notified.
HandleTerminationRequests,
/// No signal handler will be registered.
Disabled,
};
} // namespace iox2

#endif
12 changes: 11 additions & 1 deletion iceoryx2-ffi/cxx/include/iox2/waitset.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
#ifndef IOX2_WAITSET_HPP
#define IOX2_WAITSET_HPP

#include "iox/builder_addendum.hpp"
#include "iox/duration.hpp"
#include "iox/expected.hpp"
#include "iox2/callback_progression.hpp"
#include "iox2/file_descriptor.hpp"
#include "iox2/internal/iceoryx2.hpp"
#include "iox2/listener.hpp"
#include "iox2/service_type.hpp"
#include "iox2/signal_handling_mode.hpp"
#include "iox2/waitset_enums.hpp"

namespace iox2 {
Expand Down Expand Up @@ -220,6 +222,9 @@ class WaitSet {
/// * The [`WaitSetGuard`] must life at least as long as the [`WaitsSet`].
auto attach_interval(iox::units::Duration deadline) -> iox::expected<WaitSetGuard<S>, WaitSetAttachmentError>;

/// Returns the [`SignalHandlingMode`] with which the [`WaitSet`] was created.
auto signal_handling_mode() const -> SignalHandlingMode;

private:
friend class WaitSetBuilder;
explicit WaitSet(iox2_waitset_h handle);
Expand All @@ -230,9 +235,14 @@ class WaitSet {

/// The builder for the [`WaitSet`].
class WaitSetBuilder {
/// Defines the [`SignalHandlingMode`] for the [`WaitSet`]. It affects the
/// [`WaitSet::wait_and_process()`] and [`WaitSet::wait_and_process_once()`] calls
/// that returns any received [`Signal`] via its [`WaitSetRunResult`] return value.
IOX_BUILDER_OPTIONAL(SignalHandlingMode, signal_handling_mode);

public:
WaitSetBuilder();
~WaitSetBuilder();
~WaitSetBuilder() = default;

WaitSetBuilder(const WaitSetBuilder&) = delete;
WaitSetBuilder(WaitSetBuilder&&) = delete;
Expand Down
10 changes: 10 additions & 0 deletions iceoryx2-ffi/cxx/src/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ Node<T>::~Node() {
drop();
}

template <ServiceType T>
auto Node<T>::signal_handling_mode() const -> SignalHandlingMode {
return iox::into<SignalHandlingMode>(static_cast<int>(iox2_node_signal_handling_mode(&m_handle)));
}

template <ServiceType T>
auto Node<T>::name() const -> NodeNameView {
const auto* node_name_ptr = iox2_node_name(&m_handle);
Expand Down Expand Up @@ -142,6 +147,11 @@ auto NodeBuilder::create() const&& -> iox::expected<Node<T>, NodeCreationFailure
iox2_node_builder_set_config(&m_handle, &m_config.value().m_handle);
}

if (m_signal_handling_mode.has_value()) {
iox2_node_builder_set_signal_handling_mode(
&m_handle, iox::into<iox2_signal_handling_mode_e>(m_signal_handling_mode.value()));
}

iox2_node_h node_handle {};
const auto ret_val = iox2_node_builder_create(m_handle, nullptr, iox::into<iox2_service_type_e>(T), &node_handle);

Expand Down
16 changes: 12 additions & 4 deletions iceoryx2-ffi/cxx/src/waitset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT

#include "iox2/waitset.hpp"
#include "iox/into.hpp"
#include "iox2/enum_translation.hpp"
#include "iox2/internal/callback_context.hpp"

namespace iox2 {
Expand Down Expand Up @@ -151,12 +153,13 @@ WaitSetBuilder::WaitSetBuilder()
}()) {
}

WaitSetBuilder::~WaitSetBuilder() {
iox2_waitset_builder_drop(m_handle);
}

template <ServiceType S>
auto WaitSetBuilder::create() const&& -> iox::expected<WaitSet<S>, WaitSetCreateError> {
if (m_signal_handling_mode.has_value()) {
iox2_waitset_builder_set_signal_handling_mode(
&m_handle, iox::into<iox2_signal_handling_mode_e>(m_signal_handling_mode.value()));
}

iox2_waitset_h waitset_handle {};
auto result = iox2_waitset_builder_create(m_handle, iox::into<iox2_service_type_e>(S), nullptr, &waitset_handle);

Expand Down Expand Up @@ -207,6 +210,11 @@ void WaitSet<S>::drop() {
}
}

template <ServiceType S>
auto WaitSet<S>::signal_handling_mode() const -> SignalHandlingMode {
return iox::into<SignalHandlingMode>(static_cast<int>(iox2_waitset_signal_handling_mode(&m_handle)));
}

template <ServiceType S>
auto WaitSet<S>::capacity() const -> uint64_t {
return iox2_waitset_capacity(&m_handle);
Expand Down
13 changes: 13 additions & 0 deletions iceoryx2-ffi/cxx/tests/src/node_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,17 @@ TYPED_TEST(NodeTest, created_nodes_can_be_listed) {
ASSERT_TRUE(result.has_value());
ASSERT_THAT(counter, Eq(0));
}

TYPED_TEST(NodeTest, signal_handling_mode_can_be_set) {
constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE;

auto sut_1 = NodeBuilder().signal_handling_mode(SignalHandlingMode::Disabled).create<SERVICE_TYPE>().expect("");
auto sut_2 = NodeBuilder()
.signal_handling_mode(SignalHandlingMode::HandleTerminationRequests)
.create<SERVICE_TYPE>()
.expect("");

ASSERT_THAT(sut_1.signal_handling_mode(), Eq(SignalHandlingMode::Disabled));
ASSERT_THAT(sut_2.signal_handling_mode(), Eq(SignalHandlingMode::HandleTerminationRequests));
}
} // namespace
13 changes: 13 additions & 0 deletions iceoryx2-ffi/cxx/tests/src/waitset_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,17 @@ TYPED_TEST(WaitSetTest, triggering_everything_works) {
ASSERT_THAT(triggered, Eq(true));
}
}

TYPED_TEST(WaitSetTest, signal_handling_mode_can_be_set) {
constexpr ServiceType SERVICE_TYPE = TestFixture::TYPE;

auto sut_1 = WaitSetBuilder().signal_handling_mode(SignalHandlingMode::Disabled).create<SERVICE_TYPE>().expect("");
auto sut_2 = WaitSetBuilder()
.signal_handling_mode(SignalHandlingMode::HandleTerminationRequests)
.create<SERVICE_TYPE>()
.expect("");

ASSERT_THAT(sut_1.signal_handling_mode(), Eq(SignalHandlingMode::Disabled));
ASSERT_THAT(sut_2.signal_handling_mode(), Eq(SignalHandlingMode::HandleTerminationRequests));
}
} // namespace
2 changes: 2 additions & 0 deletions iceoryx2-ffi/ffi/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mod service_builder;
mod service_builder_event;
mod service_builder_pub_sub;
mod service_name;
mod signal_handling_mode;
mod static_config;
mod static_config_event;
mod static_config_publish_subscribe;
Expand Down Expand Up @@ -85,6 +86,7 @@ pub use service_builder::*;
pub use service_builder_event::*;
pub use service_builder_pub_sub::*;
pub use service_name::*;
pub use signal_handling_mode::*;
pub use static_config::*;
pub use static_config_event::*;
pub use static_config_publish_subscribe::*;
Expand Down
21 changes: 21 additions & 0 deletions iceoryx2-ffi/ffi/src/api/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ use core::ffi::{c_char, c_int};
use core::mem::ManuallyDrop;
use std::time::Duration;

use super::iox2_signal_handling_mode_e;

// BEGIN type definition

#[repr(C)]
Expand Down Expand Up @@ -289,6 +291,25 @@ pub unsafe extern "C" fn iox2_node_config(node_handle: iox2_node_h_ref) -> iox2_
}
}

/// Returns the [`iox2_signal_handling_mode_e`] with which the node was created.
///
/// # Safety
///
/// * The `node_handle` must be valid and obtained by [`iox2_node_builder_create`](crate::iox2_node_builder_create)!
#[no_mangle]
pub unsafe extern "C" fn iox2_node_signal_handling_mode(
node_handle: iox2_node_h_ref,
) -> iox2_signal_handling_mode_e {
node_handle.assert_non_null();

let node = &mut *node_handle.as_type();

match node.service_type {
iox2_service_type_e::IPC => node.value.as_ref().ipc.signal_handling_mode().into(),
iox2_service_type_e::LOCAL => node.value.as_ref().local.signal_handling_mode().into(),
}
}

/// Returns the [`iox2_node_id_ptr`](crate::iox2_node_id_ptr), an immutable pointer to the node id.
///
/// # Safety
Expand Down
29 changes: 25 additions & 4 deletions iceoryx2-ffi/ffi/src/api/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use iceoryx2_ffi_macros::iceoryx2_ffi;

use core::ffi::{c_char, c_int};

use super::iox2_signal_handling_mode_e;

// BEGIN types definition

#[repr(C)]
Expand Down Expand Up @@ -162,16 +164,14 @@ pub unsafe extern "C" fn iox2_node_builder_new(
/// * `node_name_ptr` - Must be a valid [`iox2_node_name_ptr`], e.g. obtained by [`iox2_node_name_new`](crate::iox2_node_name_new) and converted
/// by [`iox2_cast_node_name_ptr`](crate::iox2_cast_node_name_ptr)
///
/// Returns IOX2_OK
///
/// # Safety
///
/// * `node_builder_handle` as well as `node_name_ptr` must be valid handles
#[no_mangle]
pub unsafe extern "C" fn iox2_node_builder_set_name(
node_builder_handle: iox2_node_builder_h_ref,
node_name_ptr: iox2_node_name_ptr,
) -> c_int {
) {
node_builder_handle.assert_non_null();
debug_assert!(!node_name_ptr.is_null());

Expand All @@ -180,8 +180,29 @@ pub unsafe extern "C" fn iox2_node_builder_set_name(
let node_builder = node_builder_struct.take().unwrap();
let node_builder = node_builder.name(&*node_name_ptr);
node_builder_struct.set(node_builder);
}

IOX2_OK
/// Sets the [`iox2_signal_handling_mode_e`] for the [`iox2_node_h`].
///
/// # Arguments
///
/// * `node_builder_handle` - Must be a valid [`iox2_node_builder_h_ref`] obtained by [`iox2_node_builder_new`].
///
/// # Safety
///
/// * `node_builder_handle` must be a valid handle
#[no_mangle]
pub unsafe extern "C" fn iox2_node_builder_set_signal_handling_mode(
node_builder_handle: iox2_node_builder_h_ref,
signal_handling_mode: iox2_signal_handling_mode_e,
) {
node_builder_handle.assert_non_null();

let node_builder_struct = &mut *node_builder_handle.as_type();

let node_builder = node_builder_struct.take().unwrap();
let node_builder = node_builder.signal_handling_mode(signal_handling_mode.into());
node_builder_struct.set(node_builder);
}

/// Sets the node config for the builder
Expand Down
Loading

0 comments on commit 11a446f

Please sign in to comment.