Skip to content

Commit

Permalink
Ensure that we break bonds in lifecycle node/manager prior to rcl_shu…
Browse files Browse the repository at this point in the history
…tdown.

Partial fix for Issue ros-navigation#3271

Signed-off-by: mbryan <matthew.bryan@dell.com>
  • Loading branch information
mbryan committed Jan 24, 2023
1 parent ff958bb commit bc34898
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,13 @@ class LifecycleManager : public rclcpp::Node
*/
bool resume();

/**
* @brief Perform preshutdown activities before our Context is shutdown.
* Note that this is related to our Context's shutdown sequence, not the
* lifecycle node state machine or shutdown().
*/
void onRclPreshutdown();

// Support function for creating service clients
/**
* @brief Support function for creating service clients
Expand Down Expand Up @@ -186,6 +193,14 @@ class LifecycleManager : public rclcpp::Node
*/
void CreateActiveDiagnostic(diagnostic_updater::DiagnosticStatusWrapper & stat);

/**
* Register our preshutdown callback for this Node's rcl Context.
* The callback fires before this Node's Context is shutdown.
* Note this is not directly related to the lifecycle state machine or the
* shutdown() instance function.
*/
void registerRclPreshutdownCallback();

// Timer thread to look at bond connections
rclcpp::TimerBase::SharedPtr init_timer_;
rclcpp::TimerBase::SharedPtr bond_timer_;
Expand Down
31 changes: 31 additions & 0 deletions nav2_lifecycle_manager/src/lifecycle_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ LifecycleManager::LifecycleManager(const rclcpp::NodeOptions & options)
declare_parameter("bond_respawn_max_duration", 10.0);
declare_parameter("attempt_respawn_reconnection", true);

registerRclPreshutdownCallback();

node_names_ = get_parameter("node_names").as_string_array();
get_parameter("autostart", autostart_);
double bond_timeout_s;
Expand Down Expand Up @@ -378,6 +380,35 @@ LifecycleManager::destroyBondTimer()
}
}

void
LifecycleManager::onRclPreshutdown()
{
RCLCPP_INFO(
get_logger(), "Running Nav2 LifecycleManager rcl preshutdown (%s)",
this->get_name());

destroyBondTimer();

/*
* Dropping the bond map is what we really need here, but we drop the others
* to prevent the bond map being used. Likewise, squash the service thread.
*/
service_thread_.reset();
node_names_.clear();
node_map_.clear();
bond_map_.clear();
}

void
LifecycleManager::registerRclPreshutdownCallback()
{
rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();

context->add_pre_shutdown_callback(
std::bind(&LifecycleManager::onRclPreshutdown, this)
);
}

void
LifecycleManager::checkBondConnections()
{
Expand Down
15 changes: 15 additions & 0 deletions nav2_util/include/nav2_util/lifecycle_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ class LifecycleNode : public rclcpp_lifecycle::LifecycleNode
return nav2_util::CallbackReturn::SUCCESS;
}

/**
* @brief Perform preshutdown activities before our Context is shutdown.
* Note that this is related to our Context's shutdown sequence, not the
* lifecycle node state machine.
*/
virtual void on_rcl_preshutdown();

/**
* @brief Create bond connection to lifecycle manager
*/
Expand All @@ -183,6 +190,14 @@ class LifecycleNode : public rclcpp_lifecycle::LifecycleNode
*/
void printLifecycleNodeNotification();

/**
* Register our preshutdown callback for this Node's rcl Context.
* The callback fires before this Node's Context is shutdown.
* Note this is not directly related to the lifecycle state machine.
*/
void register_rcl_preshutdown_callback();
std::unique_ptr<rclcpp::PreShutdownCallbackHandle> rcl_preshutdown_cb_handle_{nullptr};

// Connection to tell that server is still up
std::unique_ptr<bond::Bond> bond_{nullptr};
};
Expand Down
27 changes: 27 additions & 0 deletions nav2_util/src/lifecycle_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ LifecycleNode::LifecycleNode(
bond::msg::Constants::DISABLE_HEARTBEAT_TIMEOUT_PARAM, true));

printLifecycleNodeNotification();

register_rcl_preshutdown_callback();
}

LifecycleNode::~LifecycleNode()
Expand All @@ -48,6 +50,13 @@ LifecycleNode::~LifecycleNode()
on_deactivate(get_current_state());
on_cleanup(get_current_state());
}

if (rcl_preshutdown_cb_handle_) {
rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();
context->remove_pre_shutdown_callback(*(rcl_preshutdown_cb_handle_.get()));
rcl_preshutdown_cb_handle_.reset();
destroyBond();
}
}

void LifecycleNode::createBond()
Expand All @@ -64,6 +73,24 @@ void LifecycleNode::createBond()
bond_->start();
}

void LifecycleNode::on_rcl_preshutdown()
{
RCLCPP_INFO(
get_logger(), "Running Nav2 LifecycleNode rcl preshutdown (%s)",
this->get_name());
destroyBond();
}

void LifecycleNode::register_rcl_preshutdown_callback()
{
rclcpp::Context::SharedPtr context = get_node_base_interface()->get_context();

rcl_preshutdown_cb_handle_ = std::make_unique<rclcpp::PreShutdownCallbackHandle>(
context->add_pre_shutdown_callback(
std::bind(&LifecycleNode::on_rcl_preshutdown, this))
);
}

void LifecycleNode::destroyBond()
{
RCLCPP_INFO(get_logger(), "Destroying bond (%s) to lifecycle manager.", this->get_name());
Expand Down

0 comments on commit bc34898

Please sign in to comment.