@@ -310,9 +310,16 @@ Context::shutdown(const std::string & reason)
310310
311311 // call each pre-shutdown callback
312312 {
313- std::lock_guard<std::mutex> lock{pre_shutdown_callbacks_mutex_};
314- for (const auto & callback : pre_shutdown_callbacks_) {
315- (*callback)();
313+ std::lock_guard<std::recursive_mutex> lock{pre_shutdown_callbacks_mutex_};
314+ // callbacks may delete other callbacks during the execution,
315+ // therefore we need to save a copy and check before execution
316+ // if the next callback is still present
317+ auto cpy = pre_shutdown_callbacks_;
318+ for (const auto & callback : cpy) {
319+ auto it = std::find (pre_shutdown_callbacks_.begin (), pre_shutdown_callbacks_.end (), callback);
320+ if (it != pre_shutdown_callbacks_.end ()) {
321+ (*callback)();
322+ }
316323 }
317324 }
318325
@@ -325,9 +332,16 @@ Context::shutdown(const std::string & reason)
325332 shutdown_reason_ = reason;
326333 // call each shutdown callback
327334 {
328- std::lock_guard<std::mutex> lock (on_shutdown_callbacks_mutex_);
329- for (const auto & callback : on_shutdown_callbacks_) {
330- (*callback)();
335+ std::lock_guard<std::recursive_mutex> lock (on_shutdown_callbacks_mutex_);
336+ // callbacks may delete other callbacks during the execution,
337+ // therefore we need to save a copy and check before execution
338+ // if the next callback is still present
339+ auto cpy = on_shutdown_callbacks_;
340+ for (const auto & callback : cpy) {
341+ auto it = std::find (on_shutdown_callbacks_.begin (), on_shutdown_callbacks_.end (), callback);
342+ if (it != on_shutdown_callbacks_.end ()) {
343+ (*callback)();
344+ }
331345 }
332346 }
333347
@@ -398,10 +412,10 @@ Context::add_shutdown_callback(
398412 shutdown_type == ShutdownType::pre_shutdown || shutdown_type == ShutdownType::on_shutdown);
399413
400414 if constexpr (shutdown_type == ShutdownType::pre_shutdown) {
401- std::lock_guard<std::mutex > lock (pre_shutdown_callbacks_mutex_);
415+ std::lock_guard<std::recursive_mutex > lock (pre_shutdown_callbacks_mutex_);
402416 pre_shutdown_callbacks_.emplace_back (callback_shared_ptr);
403417 } else {
404- std::lock_guard<std::mutex > lock (on_shutdown_callbacks_mutex_);
418+ std::lock_guard<std::recursive_mutex > lock (on_shutdown_callbacks_mutex_);
405419 on_shutdown_callbacks_.emplace_back (callback_shared_ptr);
406420 }
407421
@@ -421,7 +435,7 @@ Context::remove_shutdown_callback(
421435 }
422436
423437 const auto remove_callback = [&callback_shared_ptr](auto & mutex, auto & callback_vector) {
424- const std::lock_guard<std::mutex > lock (mutex);
438+ const std::lock_guard<std::recursive_mutex > lock (mutex);
425439 auto iter = callback_vector.begin ();
426440 for (; iter != callback_vector.end (); iter++) {
427441 if ((*iter).get () == callback_shared_ptr.get ()) {
@@ -462,7 +476,7 @@ std::vector<rclcpp::Context::ShutdownCallback>
462476Context::get_shutdown_callback () const
463477{
464478 const auto get_callback_vector = [](auto & mutex, auto & callback_set) {
465- const std::lock_guard<std::mutex > lock (mutex);
479+ const std::lock_guard<std::recursive_mutex > lock (mutex);
466480 std::vector<rclcpp::Context::ShutdownCallback> callbacks;
467481 for (auto & callback : callback_set) {
468482 callbacks.push_back (*callback);
0 commit comments