Skip to content

fix(gateway): defer a shutdown signal until startup is done - #734

Merged
bburda merged 1 commit into
fix/shadowed-node-servicesfrom
fix/gateway-startup-signal
Oct 21, 2026
Merged

bburda merged 1 commit into
fix/shadowed-node-servicesfrom
fix/gateway-startup-signal

Conversation

@bburda

@bburda bburda commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Pull Request

Summary

A SIGINT or SIGTERM that arrives while the gateway is still starting ends it with exit code 0, through the same teardown as a shutdown after startup.

  • main blocks SIGINT and SIGTERM before rclcpp::init (with SignalHandlerOptions::None) and keeps them blocked until startup is done. It then installs rclcpp's handlers and unblocks, so a signal sent meanwhile is delivered at that point, the context shuts down, spin returns at once and the explicit teardown runs.
  • A shutdown inside the startup used to end in exit code 1 (the next rcl call threw on the shut-down context), or in an abort: rclcpp's NodeGraph::get_graph_event clears its listener flag before add_node throws, and the node's destructor then throws NodeNotFoundError.
  • After startup, signals are handled by rclcpp exactly as before.
  • Threads that start during startup keep the blocked mask, and exec keeps it too. DefaultScriptProvider resets the mask in the forked child, so stop ends a script with SIGTERM.
  • The OPC-UA startup sweep runs during construction. Its cancel check also reads a pending SIGINT or SIGTERM with sigpending(), so a stop still ends the sweep, and the gateway exits once startup is done.

Issue


Type

  • Bug fix
  • New feature or tests
  • Breaking change
  • Documentation only

Testing

  • ./scripts/test.sh integ --packages-select ros2_medkit_integration_tests runs test_gateway_startup_signal. It starts the real gateway_node repeatedly, signals it 0 to 10 ms after each of five startup log lines and once it is spinning, and expects exit code 0 every time.
  • test_scripts_api checks that stop ends the script process.
  • ./scripts/test.sh integ --packages-select ros2_medkit_opcua runs test_opcua_startup_sweep_signal, which sends each signal during a startup sweep against a silent listener on port 4840.

Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Tests were added or updated if needed
  • Docs were updated if behavior or public API changed

@bburda
bburda added this pull request to stack #728 October 19, 2026 10:58
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from 71ccbc3 to fcf48bb Compare October 19, 2026 12:58
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from fcf48bb to de076e7 Compare October 19, 2026 15:19
@bburda bburda self-assigned this Oct 19, 2026
Comment thread src/ros2_medkit_gateway/src/main.cpp
Comment thread src/ros2_medkit_gateway/src/main.cpp
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from de076e7 to 7a8d189 Compare October 20, 2026 10:54
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from 7a8d189 to 7d126e0 Compare October 20, 2026 12:47
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from 7d126e0 to 50d77dd Compare October 20, 2026 12:55
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from 50d77dd to f6dbf30 Compare October 20, 2026 20:02
A SIGINT or SIGTERM during startup shut the rclcpp context down while
main was still building the gateway. The next rcl call threw and main
exited 1, or the gateway aborted: NodeGraph::get_graph_event clears its
graph listener flag before add_node throws, and ~NodeGraph then throws
NodeNotFoundError.

main now blocks both signals before rclcpp::init, which runs with
SignalHandlerOptions::None, and keeps them blocked until startup is
done. It then installs rclcpp's handlers and unblocks, so a signal sent
meanwhile shuts the context down at that point and the normal teardown
runs.

Threads that start during startup keep the blocked mask, and exec keeps
it too. DefaultScriptProvider resets the mask in the forked child, so the
stop action ends a script with SIGTERM.

The OPC-UA startup sweep runs during construction, and it stopped only
when rclcpp::ok() turned false. It now also reads a pending SIGINT or
SIGTERM with sigpending(), so a stop still ends the sweep, and the
gateway exits once startup is done.

test_scripts_api checks that stop ends the script process.
test_opcua_startup_sweep_signal sends each signal during a sweep against
a silent listener on port 4840.
@bburda
bburda force-pushed the fix/gateway-startup-signal branch from f6dbf30 to d743377 Compare October 21, 2026 07:11
@bburda
bburda merged commit 40f7315 into main Oct 21, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] gateway_node exits 1 or aborts on SIGINT during startup

2 participants