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

[#528] make signal registration optional #529

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