Skip to content

EventsExecutor segfaults when a task raises any exception #1641

Description

@nadavelkabets

Environment

ROS2 Rolling (tested on both current HEAD and commit 0ce60eb)
Ubuntu 24.04 (Noble), aarch64
Python 3.12.3

Code to reproduce

def test_coroutine_exception_after_await(self) -> None:
    """Exception in a coroutine after awaiting a future must propagate."""
    self.assertIsNotNone(self.node.handle)
    for cls in [EventsExecutor]:
        with self.subTest(cls=cls):
            executor = cls(context=self.context)
            executor.add_node(self.node)

            first_fut = executor.create_future()
            second_fut = executor.create_future()

            async def coro_that_raises() -> None:
                first_fut.set_result(None)
                await second_fut
                raise RuntimeError('Expected error after await')

            task = executor.create_task(coro_that_raises)

            executor.spin_until_future_complete(first_fut, timeout_sec=5)
            self.assertFalse(task.done())
            # Resolve the inner future — triggers resume
            second_fut.set_result(None)

            # The resumed coroutine should raise, and spin must propagate it
            with self.assertRaises(RuntimeError) as cm:
                executor.spin_until_future_complete(task, timeout_sec=5)
            self.assertIn('Expected error after await', str(cm.exception))

GDB backtrace

Thread 1 "python3" received signal SIGSEGV, Segmentation fault.
__strlen_asimd () at ../sysdeps/aarch64/multiarch/strlen_asimd.S:96

#0  __strlen_asimd () at ../sysdeps/aarch64/multiarch/strlen_asimd.S:96
#1  0x000000000052cb68 in PyUnicode_FromString ()
#2  0x0000fffff5e6cb94 [PAC] in pybind11::str::str (this=0xffffffff7228, c=0x0) at /usr/include/pybind11/pytypes.h:1542
#3  0x0000fffff5e8284c in pybind11::detail::object_api<pybind11::handle>::operator[] (this=0x179b858, key=0x0) at /usr/include/pybind11/pytypes.h:2456
#4  0x0000fffff5f5643c in rclpy::events_executor::EventsExecutor::IterateTask (this=0x179b760, task=...) at /home/user/workspace/src/rclpy/rclpy/src/rclpy/events_executor/events_executor.cpp:841
#5  0x0000fffff5f818ac in std::__invoke_impl<void, void (rclpy::events_executor::EventsExecutor::*&)(pybind11::handle), rclpy::events_executor::EventsExecutor*&, pybind11::handle&> (__f=@0x1a5ce00: (void (rclpy::events_executor::EventsExecutor::*)(rclpy::events_executor::EventsExecutor * const, pybind11::handle)) 0xfffff5f561fc <rclpy::events_executor::EventsExecutor::IterateTask(pybind11::handle)>, __t=@0x1a5ce18: 0x179b760) at /usr/include/c++/13/bits/invoke.h:74
#6  0x0000fffff5f7fad8 in std::__invoke<void (rclpy::events_executor::EventsExecutor::*&)(pybind11::handle), rclpy::events_executor::EventsExecutor*&, pybind11::handle&> (__fn=@0x1a5ce00: (void (rclpy::events_executor::EventsExecutor::*)(rclpy::events_executor::EventsExecutor * const, pybind11::handle)) 0xfffff5f561fc <rclpy::events_executor::EventsExecutor::IterateTask(pybind11::handle)>) at /usr/include/c++/13/bits/invoke.h:96
#7  0x0000fffff5f7da60 in std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)>::__call<void, , 0ul, 1ul>(std::tuple<>&&, std::_Index_tuple<0ul, 1ul>) (this=0x1a5ce00, __args=...) at /usr/include/c++/13/functional:506
#8  0x0000fffff5f78cac in std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)>::operator()<, void>() (this=0x1a5ce00) at /usr/include/c++/13/functional:591
#9  0x0000fffff5f72e2c in std::__invoke_impl<void, std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)>&>(std::__invoke_other, std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)>&) (__f=...) at /usr/include/c++/13/bits/invoke.h:61
#10 0x0000fffff5f69b28 in std::__invoke_r<void, std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)>&>(std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)>&) (__fn=...) at /usr/include/c++/13/bits/invoke.h:111
#11 0x0000fffff5f637fc in std::_Function_handler<void (), std::_Bind<void (rclpy::events_executor::EventsExecutor::*(rclpy::events_executor::EventsExecutor*, pybind11::handle))(pybind11::handle)> >::_M_invoke(std::_Any_data const&) (__functor=...) at /usr/include/c++/13/bits/std_function.h:290
#12 0x0000fffff5f84284 in std::function<void()>::operator() (this=0xffffffff7518) at /usr/include/c++/13/bits/std_function.h:591
#13 0x0000fffff5f83e80 in rclpy::events_executor::EventsQueue::RunUntil (this=0x179b790, deadline=std::chrono::_V2::steady_clock time_point = { 5953877619367ns }) at /home/user/workspace/src/rclpy/rclpy/src/rclpy/events_executor/events_queue.cpp:48
#14 0x0000fffff5f50054 in rclpy::events_executor::EventsExecutor::spin (this=0x179b760, timeout_sec=std::optional = {...}, stop_after_user_callback=false) at /home/user/workspace/src/rclpy/rclpy/src/rclpy/events_executor/events_executor.cpp:176
#15 0x0000fffff5f50358 in rclpy::events_executor::EventsExecutor::spin_until_future_complete (this=0x179b760, future=..., timeout_sec=std::optional = {...}, stop_after_user_callback=false) at /home/user/workspace/src/rclpy/rclpy/src/rclpy/events_executor/events_executor.cpp:194

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions