Stop retaining ownership of the rcl context in GraphListener (#946)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
This commit is contained in:
parent
914ea81c63
commit
01d03c5d4e
2 changed files with 13 additions and 6 deletions
|
@ -177,7 +177,6 @@ private:
|
||||||
std::vector<rclcpp::node_interfaces::NodeGraphInterface *> node_graph_interfaces_;
|
std::vector<rclcpp::node_interfaces::NodeGraphInterface *> node_graph_interfaces_;
|
||||||
|
|
||||||
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
|
rcl_guard_condition_t interrupt_guard_condition_ = rcl_get_zero_initialized_guard_condition();
|
||||||
std::shared_ptr<rcl_context_t> interrupt_guard_condition_context_;
|
|
||||||
rcl_guard_condition_t * shutdown_guard_condition_;
|
rcl_guard_condition_t * shutdown_guard_condition_;
|
||||||
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
rcl_wait_set_t wait_set_ = rcl_get_zero_initialized_wait_set();
|
||||||
};
|
};
|
||||||
|
|
|
@ -39,17 +39,15 @@ GraphListener::GraphListener(std::shared_ptr<rclcpp::Context> parent_context)
|
||||||
: parent_context_(parent_context),
|
: parent_context_(parent_context),
|
||||||
is_started_(false),
|
is_started_(false),
|
||||||
is_shutdown_(false),
|
is_shutdown_(false),
|
||||||
interrupt_guard_condition_context_(nullptr),
|
|
||||||
shutdown_guard_condition_(nullptr)
|
shutdown_guard_condition_(nullptr)
|
||||||
{
|
{
|
||||||
// TODO(wjwwood): make a guard condition class in rclcpp so this can be tracked
|
// TODO(wjwwood): make a guard condition class in rclcpp so this can be tracked
|
||||||
// automatically with the rcl guard condition
|
// automatically with the rcl guard condition
|
||||||
// hold on to this context to prevent it from going out of scope while this
|
// hold on to this context to prevent it from going out of scope while this
|
||||||
// guard condition is using it.
|
// guard condition is using it.
|
||||||
interrupt_guard_condition_context_ = parent_context->get_rcl_context();
|
|
||||||
rcl_ret_t ret = rcl_guard_condition_init(
|
rcl_ret_t ret = rcl_guard_condition_init(
|
||||||
&interrupt_guard_condition_,
|
&interrupt_guard_condition_,
|
||||||
interrupt_guard_condition_context_.get(),
|
parent_context->get_rcl_context().get(),
|
||||||
rcl_guard_condition_get_default_options());
|
rcl_guard_condition_get_default_options());
|
||||||
if (RCL_RET_OK != ret) {
|
if (RCL_RET_OK != ret) {
|
||||||
throw_from_rcl_error(ret, "failed to create interrupt guard condition");
|
throw_from_rcl_error(ret, "failed to create interrupt guard condition");
|
||||||
|
@ -72,6 +70,10 @@ GraphListener::start_if_not_started()
|
||||||
}
|
}
|
||||||
if (!is_started_) {
|
if (!is_started_) {
|
||||||
// Initialize the wait set before starting.
|
// Initialize the wait set before starting.
|
||||||
|
auto parent_context = parent_context_.lock();
|
||||||
|
if (!parent_context) {
|
||||||
|
throw std::runtime_error("parent context was destroyed");
|
||||||
|
}
|
||||||
rcl_ret_t ret = rcl_wait_set_init(
|
rcl_ret_t ret = rcl_wait_set_init(
|
||||||
&wait_set_,
|
&wait_set_,
|
||||||
0, // number_of_subscriptions
|
0, // number_of_subscriptions
|
||||||
|
@ -80,7 +82,7 @@ GraphListener::start_if_not_started()
|
||||||
0, // number_of_clients
|
0, // number_of_clients
|
||||||
0, // number_of_services
|
0, // number_of_services
|
||||||
0, // number_of_events
|
0, // number_of_events
|
||||||
interrupt_guard_condition_context_.get(),
|
parent_context->get_rcl_context().get(),
|
||||||
rcl_get_default_allocator());
|
rcl_get_default_allocator());
|
||||||
if (RCL_RET_OK != ret) {
|
if (RCL_RET_OK != ret) {
|
||||||
throw_from_rcl_error(ret, "failed to initialize wait set");
|
throw_from_rcl_error(ret, "failed to initialize wait set");
|
||||||
|
@ -141,6 +143,13 @@ GraphListener::run_loop()
|
||||||
}
|
}
|
||||||
// This lock is released when the loop continues or exits.
|
// This lock is released when the loop continues or exits.
|
||||||
std::lock_guard<std::mutex> nodes_lock(node_graph_interfaces_mutex_, std::adopt_lock);
|
std::lock_guard<std::mutex> nodes_lock(node_graph_interfaces_mutex_, std::adopt_lock);
|
||||||
|
// Ensure that the context doesn't go out of scope.
|
||||||
|
auto parent_context = parent_context_.lock();
|
||||||
|
if (!parent_context) {
|
||||||
|
// The parent context may be destroyed before this loop is stopped.
|
||||||
|
// In that case, the loop is broken and the function just returns silently.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Resize the wait set if necessary.
|
// Resize the wait set if necessary.
|
||||||
const size_t node_graph_interfaces_size = node_graph_interfaces_.size();
|
const size_t node_graph_interfaces_size = node_graph_interfaces_.size();
|
||||||
|
@ -350,7 +359,6 @@ GraphListener::__shutdown(bool should_throw)
|
||||||
listener_thread_.join();
|
listener_thread_.join();
|
||||||
}
|
}
|
||||||
rcl_ret_t ret = rcl_guard_condition_fini(&interrupt_guard_condition_);
|
rcl_ret_t ret = rcl_guard_condition_fini(&interrupt_guard_condition_);
|
||||||
interrupt_guard_condition_context_.reset(); // release context guard condition was using
|
|
||||||
if (RCL_RET_OK != ret) {
|
if (RCL_RET_OK != ret) {
|
||||||
throw_from_rcl_error(ret, "failed to finalize interrupt guard condition");
|
throw_from_rcl_error(ret, "failed to finalize interrupt guard condition");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue