Skip to content

refactor(agnocastlib): Refactor epoll processing and clean up hardcoded event-specific logic#1245

Open
ruth561 wants to merge 4 commits intomainfrom
refactor/agnocast_epoll
Open

refactor(agnocastlib): Refactor epoll processing and clean up hardcoded event-specific logic#1245
ruth561 wants to merge 4 commits intomainfrom
refactor/agnocast_epoll

Conversation

@ruth561
Copy link
Copy Markdown
Collaborator

@ruth561 ruth561 commented Apr 9, 2026

Description

This PR refactors agnocast_epoll.cpp and .hpp to eliminate tight dependencies, improve code extensibility, and optimize how Executors handle epoll updates.

Key Changes & Motivations

Replaced Global Polling with Individual Notifications

  • Changes: Removed the need_epoll_updates global variable. Replaced the polling approach with a new mechanism that notifies each Executor individually when an update is needed.
  • Impact: Previously, Executors had to poll the global variable, forcing all Executors to process updates until every single Executor was finished. This was inefficient.

Decoupled Event Handling

  • Changes: Removed hardcoded, event-specific implementations from agnocast_epoll.cpp and .hpp and moved them into their respective, event-specific files.
  • Impact: The previous tight coupling made it difficult to add new events. This change significantly improves the code's extensibility for future updates.

Future-proofing

  • This change lays the groundwork for a future architecture where epoll update notifications can be sent exclusively to specific, targeted Executors rather than all of them.

Related links

close #969

How was this PR tested?

  • Autoware (required)
  • bash scripts/test/e2e_test_1to1.bash (required)
  • bash scripts/test/e2e_test_2to2.bash (required)
  • kunit tests (required when modifying the kernel module)
  • bash scripts/test/run_requires_kernel_module_tests.bash (required)
  • sample application

Notes for reviewers

Version Update Label (Required)

Please add exactly one of the following labels to this PR:

  • need-major-update: User API breaking changes
  • need-minor-update: Internal API breaking changes (heaphook/kmod/agnocastlib compatibility)
  • need-patch-update: Bug fixes and other changes

Important notes:

  • If you need need-major-update or need-minor-update, please include this in the PR title as well.
    • Example: fix(foo)[needs major version update]: bar or feat(baz)[needs minor version update]: qux
  • After receiving approval from reviewers, add the run-build-test label. The PR can only be merged after the build tests pass.

See CONTRIBUTING.md for detailed versioning rules.

@ruth561 ruth561 added run-build-test Run build-test in CI need-patch-update Bug fixes and other changes - requires PATCH version update labels Apr 9, 2026
@ruth561 ruth561 changed the title Refactor epoll processing and clean up hardcoded event-specific logic refactor(agnocastlib): Refactor epoll processing and clean up hardcoded event-specific logic Apr 9, 2026
@ruth561 ruth561 force-pushed the refactor/agnocast_epoll branch from f8c0de0 to f37d50c Compare April 9, 2026 06:21
ruth561 added 2 commits April 9, 2026 15:28
Previously, when events managed by epoll changed, we notified each Executor
to call `prepare_epoll_impl()` by setting the global atomic variable
`need_epoll_updates` to true. However, this implementation will become
problematic for future refactoring efforts aimed at extracting event-specific
processing from `agnocast_epoll.hpp` and `.cpp`.

This commit removes this global variable and introduces an alternative
notification mechanism. While the current implementation only supports
broadcasting notifications to all Executors—which leaves some performance
challenges—it establishes a 1-to-1 tracking structure for each Executor.
This lays the groundwork for implementing targeted 1-to-1 notifications
in the future.

Relates to: #969

Signed-off-by: Takumi Jin <primenumber_2_3_5@yahoo.co.jp>
Previously, all event-specific logic was hardcoded in `agnocast_epoll.cpp`
and `.hpp`. This caused dependency issues and made it difficult to add
new event types.

This commit refactors the code by categorizing events and moving their
implementations into separate source files. Key changes include:

- Change epoll_data format from u32 to u64 to hold both event kind and local identifier.
- Introduce `EpollManager` to manage and dispatch events from the Epoll class.
- Introduce `EpollEventSource` as an abstract base class for specific event handlers.
- Replace raw file descriptor `epoll_fd_` usage with the encapsulated `Epoll` class.
- Move implementation details from headers to `.cpp` files.

Relates to: #969

Signed-off-by: Takumi Jin <primenumber_2_3_5@yahoo.co.jp>
@ruth561 ruth561 force-pushed the refactor/agnocast_epoll branch from dd979fe to 0194636 Compare April 9, 2026 06:29
@ruth561 ruth561 requested a review from Koichi98 April 9, 2026 06:32
@ruth561 ruth561 marked this pull request as ready for review April 9, 2026 06:48
@Koichi98 Koichi98 requested a review from Copilot April 9, 2026 06:55
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors agnocastlib’s epoll integration to remove global “polling for updates” (need_epoll_updates), introduce per-executor update tracking, and decouple event-type-specific epoll handling into dedicated event-source classes.

Changes:

  • Replaced the global epoll-update flag with an EpollUpdateDispatcher/EpollUpdateTracker mechanism so each executor can independently decide when to re-prepare epoll.
  • Introduced EpollManager + EpollEventSource abstraction, plus Epoll wrapper that packs (event_type, local_id) into epoll_event.data.u64.
  • Moved subscription/timer epoll prepare/handle logic out of agnocast_epoll.cpp into SubscriptionEventSource and TimerEventSource.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/agnocastlib/test/unit/test_mocked_agnocast.cpp Updates ID overflow tests to use new max-ID constants.
src/agnocastlib/src/node/agnocast_only_single_threaded_executor.cpp Switches epoll update triggering to epoll_update_tracker_ + epoll_manager_.
src/agnocastlib/src/node/agnocast_only_multi_threaded_executor.cpp Same as above for the MT executor variant.
src/agnocastlib/src/node/agnocast_only_executor.cpp Replaces raw epoll fd usage with EpollManager and registers shutdown via manager.
src/agnocastlib/src/agnocast_timer_info.cpp Replaces global update flag with dispatcher notification; adds TimerEventSource.
src/agnocastlib/src/agnocast_single_threaded_executor.cpp Uses per-executor update tracker instead of global flag.
src/agnocastlib/src/agnocast_multi_threaded_executor.cpp Uses per-executor update tracker instead of global flag.
src/agnocastlib/src/agnocast_executor.cpp Introduces EpollManager and per-executor tracker; delegates prepare/wait to manager.
src/agnocastlib/src/agnocast_epoll.cpp Replaces monolithic event handling with EpollManager dispatch over event sources.
src/agnocastlib/src/agnocast_epoll_update_dispatcher.cpp Adds dispatcher/tracker implementation.
src/agnocastlib/src/agnocast_epoll_event.cpp Adds Epoll wrapper implementation for add/remove/wait with packed event data.
src/agnocastlib/src/agnocast_callback_info.cpp Adds SubscriptionEventSource prepare/handle and new callback-id max check.
src/agnocastlib/include/agnocast/node/agnocast_only_executor.hpp Stores EpollManager + EpollUpdateTracker instead of raw epoll fd.
src/agnocastlib/include/agnocast/agnocast_timer_info.hpp Adds MAX_TIMER_ID and declares TimerEventSource.
src/agnocastlib/include/agnocast/agnocast_executor.hpp Stores EpollManager + EpollUpdateTracker instead of raw epoll fd.
src/agnocastlib/include/agnocast/agnocast_epoll.hpp Defines event-source abstraction and EpollManager.
src/agnocastlib/include/agnocast/agnocast_epoll_update_dispatcher.hpp Declares dispatcher/tracker API.
src/agnocastlib/include/agnocast/agnocast_epoll_event.hpp Declares packed epoll event encoding + Epoll wrapper API.
src/agnocastlib/include/agnocast/agnocast_callback_info.hpp Adds MAX_CALLBACK_INFO_ID, dispatcher notification, and declares SubscriptionEventSource.
src/agnocastlib/CMakeLists.txt Adds new source files to the shared library build.
Comments suppressed due to low confidence (1)

src/agnocastlib/include/agnocast/agnocast_epoll.hpp:10

  • agnocast_epoll.hpp uses std::function, std::array, and std::unique_ptr but does not include the corresponding standard headers. This makes the header non-self-contained and can cause compilation failures depending on include order. Add the missing includes (e.g., <functional>, <array>, <memory>) in this header.
#include "agnocast/agnocast_epoll_event.hpp"

#include <rclcpp/callback_group.hpp>

#include <atomic>
#include <mutex>
#include <shared_mutex>
#include <vector>

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

Coverage Report (jazzy)
------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
install/include/agnocast_cie_config_msgs/agnocast_cie_config_msgs/msg/detail/callback_group_info__struct.hpp
                                               6       6   100%
install/include/agnocast_cie_config_msgs/agnocast_cie_config_msgs/msg/detail/callback_group_info__traits.hpp
                                               2       0     0%   110,112
src/agnocastlib/include/agnocast/agnocast.hpp
                                              17      16    94%   257
src/agnocastlib/include/agnocast/agnocast_callback_info.hpp
                                              31      30    96%   146
src/agnocastlib/include/agnocast/agnocast_epoll.hpp
                                               9       5    55%   44,52,63,65
src/agnocastlib/include/agnocast/agnocast_epoll_event.hpp
                                               6       6   100%
src/agnocastlib/include/agnocast/agnocast_epoll_update_dispatcher.hpp
                                               7       7   100%
src/agnocastlib/include/agnocast/agnocast_publisher.hpp
                                              66      54    81%   101,113,143,146-147,149,153,158-160,222-223
src/agnocastlib/include/agnocast/agnocast_smart_pointer.hpp
                                              97      93    95%   305,310,322,327
src/agnocastlib/include/agnocast/agnocast_subscription.hpp
                                              60       9    15%   81,98-99,104,107-110,112,123,128-132,136,138-139,142-143,145,147-150,152-153,159,162,164,166-167,170,173-174,181,184,187,189,191-192,195,198-199,205,207,215-219
src/agnocastlib/include/agnocast/agnocast_timer.hpp
                                              15      12    80%   37,80,96
src/agnocastlib/include/agnocast/agnocast_timer_info.hpp
                                               6       5    83%   82
src/agnocastlib/include/agnocast/agnocast_tracepoint_wrapper.h
                                              13       7    53%   15,32,52,59,70,83
src/agnocastlib/include/agnocast/agnocast_utils.hpp
                                              15       8    53%   20-22,28,32,36,41
src/agnocastlib/include/agnocast/bridge/agnocast_bridge_ipc_event_loop_base.hpp
                                             114       0     0%   51,82,84-85,88-95,97,99-100,102,104-105,107,109-113,115-116,118-122,124-125,128-130,134,137,139-140,142,144,146-147,149,151-152,154,156-157,159,162-163,165-167,169,171,173-175,178-180,182,184-187,189-190,193,195-196,199,202,204-206,208-209,211,213,215,218-220,222-224,227,229,232-234,237-238,241,244,246-248,250,253-255,257,260-262,265,267-268,272
src/agnocastlib/include/agnocast/bridge/agnocast_bridge_node.hpp
                                             132       8     6%   44,46,55,57-58,78,81,93,96,100,102-105,108-110,115,117-121,123,125,143,146,151-153,156-158,163-169,171,173-175,177,181,184-186,189,192-194,197,201-204,206-207,210,212-213,216,219-220,222-230,233-234,239,243,246,250-251,253-254,257-260,263-264,266-272,276,278-280,283-286,288,291,293-295,297-299,302,305,307,309-313,315-317
src/agnocastlib/include/agnocast/bridge/agnocast_bridge_utils.hpp
                                               1       0     0%   21
src/agnocastlib/include/agnocast/bridge/performance/agnocast_performance_bridge_ipc_event_loop.hpp
                                               1       0     0%   14
src/agnocastlib/include/agnocast/bridge/standard/agnocast_standard_bridge_ipc_event_loop.hpp
                                               1       0     0%   14
src/agnocastlib/include/agnocast/cie_client_utils.hpp
                                               2       2   100%
src/agnocastlib/include/agnocast/message_filters/message_event.hpp
                                              11      11   100%
src/agnocastlib/include/agnocast/message_filters/parameter_adapter.hpp
                                               6       6   100%
src/agnocastlib/include/agnocast/message_filters/pass_through.hpp
                                              13      13   100%
src/agnocastlib/include/agnocast/message_filters/signal1.hpp
                                              22      22   100%
src/agnocastlib/include/agnocast/message_filters/signal9.hpp
                                              71      65    91%   287,289-292,294
src/agnocastlib/include/agnocast/message_filters/simple_filter.hpp
                                              11       7    63%   57,59,61-62
src/agnocastlib/include/agnocast/message_filters/subscriber.hpp
                                              53       0     0%   21,23-25,38,77,81-82,94,99-100,155,159-161,163,166-168,200,212,216-219,231,235-236,249,253-256,269,273,275-282,284,290,292-296,299,305,330
src/agnocastlib/include/agnocast/message_filters/sync_policies/approximate_time.hpp
                                             369     320    86%   138,148,151,154-155,165,168,170,176,278-300,334-350
src/agnocastlib/include/agnocast/message_filters/sync_policies/exact_time.hpp
                                              61      60    98%   188
src/agnocastlib/include/agnocast/message_filters/synchronizer.hpp
                                             113     101    89%   134,136-138,192,195,197-199,365,367-368
src/agnocastlib/include/agnocast/node/agnocast_arguments.hpp
                                               3       1    33%   30,32
src/agnocastlib/include/agnocast/node/agnocast_context.hpp
                                               3       1    33%   25,27
src/agnocastlib/include/agnocast/node/agnocast_node.hpp
                                              16      10    62%   75,83,424,428,457,462
src/agnocastlib/include/agnocast/node/node_interfaces/node_base.hpp
                                               1       1   100%
src/agnocastlib/include/agnocast/node/node_interfaces/node_clock.hpp
                                               1       1   100%
src/agnocastlib/include/agnocast/node/node_interfaces/node_logging.hpp
                                               1       1   100%
src/agnocastlib/include/agnocast/node/node_interfaces/node_parameters.hpp
                                               1       1   100%
src/agnocastlib/include/agnocast/node/node_interfaces/node_services.hpp
                                               1       1   100%
src/agnocastlib/include/agnocast/node/node_interfaces/node_topics.hpp
                                               1       1   100%
src/agnocastlib/src/agnocast.cpp             275       5     1%   22,24,53,56,58-64,68-70,72,74-79,81,83-88,91-96,100-101,105-109,112-113,115,117,120,122-123,125,130,132-134,136,140,142-144,146-147,150,152-153,155,157,159-162,165-169,173,175-176,181-182,185,187,190,192,194-202,205-207,211-212,215,217,219-223,225-231,233,235-236,238,241-247,249-251,253-257,267,269-270,273-275,277-278,280-282,284-285,288-289,292-293,296-299,303-304,307-309,311-312,314,316-317,320,323,325-326,329,332,336-337,340,343,347,349-350,352-353,355,357-359,362-363,369,372-373,378,381,385,387-390,393-395,397-399,405-408,410-411,414-419,422-423,425-426,428-429,431,434-435,438-439,442,446,449-451,454-457,459,461,464-468,471-473,476-480,483-485,488-489,491-494,496-498,501-503,507-510,513-516,523-524
src/agnocastlib/src/agnocast_callback_info.cpp
                                             102      80    78%   46-48,53-56,99,131-132,140,156,161-163,167-169,188,201-203
src/agnocastlib/src/agnocast_callback_isolated_executor.cpp
                                             255     197    77%   22-24,26,39-41,44-46,49-50,55,84-87,109,133,153,157,201,203-204,207-208,210-211,213,215,220-222,224,264,283,294,308-310,312,329,333,336-337,345,347-348,350,373,375-376,378,402,413,415,436,439
src/agnocastlib/src/agnocast_client.cpp       37       0     0%   16,18,20-28,31-32,34,36,38-39,42-43,46,49,52-54,56,58,62,67-68,70-73,75-76,79-80
src/agnocastlib/src/agnocast_component_container.cpp
                                              25       0     0%   7,9-10,13,15,20-22,25,27,30,32-34,36-45,47
src/agnocastlib/src/agnocast_component_container_cie.cpp
                                             142       0     0%   23-24,26,28,47,49,51-54,56,59-62,93,95,97-98,101-103,105-106,110-111,113,116-119,121,123-126,128,130,132-133,135,137-138,140,142-143,145,147,149,152,156-157,159,161-165,167-170,172-174,177-178,181-183,185-187,189,191,193-197,200,202-205,208-209,211,213,215,217-219,221-224,227-228,231-233,236,238-239,241,243-246,249-250,253-254,256,258,260-261,264-266,270,272-273,276,278,283-285,288,290,292-293,295-303
src/agnocastlib/src/agnocast_component_container_mt.cpp
                                              32       0     0%   9,11-12,17,19,24-26,29,31,33-35,38-39,41,44-45,47-49,51-60,62
src/agnocastlib/src/agnocast_epoll.cpp        31      21    67%   20-21,39-42,45,56,59-60
src/agnocastlib/src/agnocast_epoll_event.cpp
                                              36      23    63%   13-14,25,27-29,32-33,35,46,48-49,61
src/agnocastlib/src/agnocast_epoll_update_dispatcher.cpp
                                              37      24    64%   36-37,39-40,42,44-46,48-49,51,53,66
src/agnocastlib/src/agnocast_executor.cpp
                                              48      47    97%   85
src/agnocastlib/src/agnocast_multi_threaded_executor.cpp
                                              92      70    76%   19,22,36-38,48-49,52-53,56-57,60-61,64-65,69,76-77,86-88,166
src/agnocastlib/src/agnocast_publisher.cpp
                                              89       0     0%   14,16,19,21-22,24,26-27,30-31,33-34,36,40,42-51,54,57,62,64-67,70-72,74-77,80,82-87,91,93-95,98,102-105,109,113-114,122-127,131,134-135,139,142,144-149,152,154-155,158,160-161,164,167,169-174,177
src/agnocastlib/src/agnocast_single_threaded_executor.cpp
                                              43      26    60%   20,31-33,37,46-48,71,75-78,81-82,84-85
src/agnocastlib/src/agnocast_smart_pointer.cpp
                                              10       7    70%   14-16
src/agnocastlib/src/agnocast_subscription.cpp
                                              63       0     0%   7-8,10-11,13-15,17-18,20,24-37,40,43,45-50,53,55-56,59,61-62,65,68,72-77,79-82,86-87,89,91-92,94,97-98,102-103,107,109,111
src/agnocastlib/src/agnocast_timer.cpp         3       3   100%
src/agnocastlib/src/agnocast_timer_info.cpp
                                             180      53    29%   26,28,30-32,35-36,38,40,44-45,49,51,53-55,58-59,61-63,65,68-71,73,75,77,79-80,82-84,86,91,94,96-99,104,107-108,120-122,124,126-130,132-137,139-142,150,164-165,173-174,182-183,185-186,220-221,223-224,229-230,247,251-253,256,258,260,262,265-266,268,271,273-274,277,279-280,294-295,297-298,301-302,305-308,311,315,318-319,321,323-328,330-332,334-335,339,342-344,346-347
src/agnocastlib/src/agnocast_tracepoint_wrapper.c
                                              13       7    53%   34,82,114,124,146,174
src/agnocastlib/src/agnocast_utils.cpp        54      37    68%   19,70,82-84,88,90,92,95,97,100,103,106,108-109,112,114
src/agnocastlib/src/bridge/agnocast_bridge_utils.cpp
                                             102       0     0%   14,16-18,21-22,24-25,27-28,30-31,34-36,38,40-42,44,46,48-50,52-54,57,59-61,63,65,68-71,74,76-80,83-86,89,92,94-98,101-103,106,109,111-112,115,117-119,121-123,125,128,130-131,134,136-138,140-142,144,147,149-150,153-155,157-161,163,165-166,169-171,173-177
src/agnocastlib/src/bridge/performance/agnocast_performance_bridge_ipc_event_loop.cpp
                                               4       0     0%   12,16,22,24
src/agnocastlib/src/bridge/performance/agnocast_performance_bridge_loader.cpp
                                              82       0     0%   14,16,18,20-22,25-26,28,32-34,37-38,41,45-47,50-51,54,56-58,61,64-65,68-81,83,87-89,91,93-94,96,98-100,103,105-106,110-113,118-120,122,125-126,128,131-132,134-136,139-140,142-144,147,150-151,156,159-160
src/agnocastlib/src/bridge/performance/agnocast_performance_bridge_manager.cpp
                                             196       0     0%   20-23,25-26,29-32,34,36-37,40-41,44-45,47,49,51,53-54,56,58-59,61-64,67-70,72,74,76-77,82-83,85,87-90,92-96,98,100,102-105,109,112,114-116,118,120-121,123,125-126,128-130,132,134,136-138,140-142,146,148-149,151-152,154,156-157,159,161-167,170-171,173-174,177-179,181,183-184,187,191-197,200-201,203-204,207-209,211,213-214,217,222,224-226,228,230-231,233,236,238,240-243,246-247,251,254-256,259-261,264,266-267,270-272,275,278,282-283,286-290,293-294,298,300-303,305-306,309-312,315,317-318,321,325-326,329-331,334-335,338,341-343,348-349,351,353-356,358
src/agnocastlib/src/bridge/standard/agnocast_standard_bridge_ipc_event_loop.cpp
                                               4       0     0%   13,17,23,25
src/agnocastlib/src/bridge/standard/agnocast_standard_bridge_loader.cpp
                                              91       0     0%   18,20,22,24-25,27,31,33-35,38,41-42,44,49-51,54,57-59,61-62,64-67,70,73,75-76,78,81-82,85-88,90,93,96,98,104-107,109-111,113,117-119,121,124-125,127-128,130,133,137-140,142-143,145-146,148,151,154-155,157-158,160,162-164,167-169,171-174,176-178,180-181,185
src/agnocastlib/src/bridge/standard/agnocast_standard_bridge_manager.cpp
                                             257       0     0%   16-20,22-23,26-29,31,33-34,36,38-40,42-43,45,48-50,52-53,55,57,59,61-62,64,66-67,69-71,74-77,79,81,83-84,89-90,92,94-97,99-103,105,107-110,112,114,116,118-119,121-123,125,127,131-133,136-139,141,144,147-148,150,152,154-155,158,161,163,166-167,169-170,174,176,178-180,182-183,187-188,190,192-195,197-198,201-203,207-208,212,214,216-217,220-222,224,226,228-230,233,236-237,240-241,244-245,247,250-251,254,257-260,262-265,269-270,272-274,276,278,280-282,284,286-288,292,295-301,303-305,308-315,319-323,326,329,331-332,334-336,340,342-347,350-352,354-355,357,359-361,365-369,377-379,383,386-390,392,395-396,400-401,403,405-407,410-411,415-416,418-419,422-424,427-429,431,433,435-437,439-441,444,446,450,452-453,455-456
src/agnocastlib/src/cie_client_utils.cpp      65      47    72%   28,41-43,100,102,105,107-108,113-115,127,132-136
src/agnocastlib/src/node/agnocast_arguments.cpp
                                              79      37    46%   29,31,36,38-39,41,43-46,48,51-52,54-56,58,61,63,65-70,72,76,88,95,104,124,126-128,131,133-135,139-140,145,149
src/agnocastlib/src/node/agnocast_context.cpp
                                              30       0     0%   15,17-18,22-25,28,32-36,38,41-43,45,47-49,51,53-55,61-63,65,67
src/agnocastlib/src/node/agnocast_node.cpp
                                              19      19   100%
src/agnocastlib/src/node/agnocast_only_callback_isolated_executor.cpp
                                             149       0     0%   17-18,20,22,24-28,30,32,34-37,40,44,47,50-53,56-58,61-62,65-68,71-74,76-78,80-81,85,88-89,92-93,95,97-98,100,103-105,107-109,112-114,116-117,119,122,124-126,128-129,131-132,137,140-144,147-152,154-156,158-159,162-164,166-168,170,172,178,180-184,186-192,195,197,200-208,210,212,217,221-222,224-225,228-229,232-233,235,237-239,241-242,246,249-251,253-258,260,262,265-266
src/agnocastlib/src/node/agnocast_only_executor.cpp
                                             222       0     0%   18-22,24-31,33,35-37,40-43,46-48,50,53,55-58,60-61,63-66,68-69,71-74,76-78,80-82,84,87,89-90,93,95-96,100,103,106,108-111,114-117,120-121,123,126-127,130,132,134-135,137,139,141-144,146,148,156-160,162,164-168,171-173,176,180,182,187-193,195-198,200-202,204,206-212,214-215,217-218,221,223-227,229-230,233,235-239,241-242,244,247-251,253-256,258,260-264,266-269,271-273,276,281,283-284,286,292-294,297-298,300-306,308-310,313,318-320,322,324-325,327,333-336,339,341-345,347,350-353,356-361,363-365,369-370,372,374-375
src/agnocastlib/src/node/agnocast_only_multi_threaded_executor.cpp
                                              42       0     0%   10-16,18,21,23,25-28,31,33,35-37,40,42-43,45,47,49-53,57,59-60,66-70,73,76-78,80
src/agnocastlib/src/node/agnocast_only_single_threaded_executor.cpp
                                              27       0     0%   8-9,11-13,19,22,24,26-29,32,34-38,42-46,49-50,52-53
src/agnocastlib/src/node/agnocast_signal_handler.cpp
                                              45       0     0%   23,25-26,30-31,34,37-38,40-42,45-47,51,53-54,56-59,63-65,67-69,71,73-78,81,83,86-87,89,91-95,98
src/agnocastlib/src/node/node_interfaces/node_base.cpp
                                             181     104    57%   33,42,56-59,61-62,74-77,79-80,124,126,129,133,136,140,143,147,150,154,181,187,189-191,198,200,202-205,207-209,222,224,233,238,242,247,250,254,269-272,274,283-284,286,299-301,304-305,308-309,321-325,339-343,345,353,368,370,373,375
src/agnocastlib/src/node/node_interfaces/node_clock.cpp
                                               7       5    71%   16,18
src/agnocastlib/src/node/node_interfaces/node_logging.cpp
                                               8       2    25%   12,14,17,19,25,28
src/agnocastlib/src/node/node_interfaces/node_parameters.cpp
                                             418      88    21%   37-41,43,45,47,49,57,61-66,68,70-71,73,85,91,100,111-113,116,125,127,130,132-135,143-146,148-151,153-154,156-157,159-161,165-168,170-173,175-176,178-180,182-184,187,189,192,196-198,211-213,216,229-230,234,238,249,255,267,283,289-291,293,295-299,308,320,322-324,339,360,364-365,367,369,372,375,378-381,383,385-386,388-389,391,394,396,398,400,403-404,413,416-417,419-422,424-425,427,430-431,433,439-441,444-445,449-450,452,454,457,461,465-468,476-477,480-482,485,487,489-490,493,500-506,509,511,514-519,521,527-535,537,543,547,549-550,553-554,558,560,562,565,569-570,572-573,575,584-585,587,590-591,593-595,597-598,600,602,604-605,607,609,611-616,618-619,621,624,626-627,629,632-634,638-639,641,644-646,648-657,663-664,667-668,670,673-675,677-682,684,690-691,694-695,697,700-701,703,705-707,710,712-716,718-720,722-724,726-729,732-733,738-745,747,749-750,754,759-760,762-763,765-767,769,772-773,775,777-779,781,783,785,788,795,797,801,803,806,809,812,815
src/agnocastlib/src/node/node_interfaces/node_services.cpp
                                               8       2    25%   12,18,21,28,31,33
src/agnocastlib/src/node/node_interfaces/node_time_source.cpp
                                             101      49    48%   49,53-54,57,60,81,92,94,96,100,103-104,115,118-119,125,132-134,137-139,145,149,151-152,154,157-158,163,165,167-168,172,175-179,183-187,193-195,200,202-203,206-207
src/agnocastlib/src/node/node_interfaces/node_topics.cpp
                                              16       4    25%   18,20,23,32,35,42,45,54,57,64,67,71
------------------------------------------------------------------------------
TOTAL                                       5079    1848    36%
------------------------------------------------------------------------------

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

Coverage Report (humble)
------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
install/include/agnocast_cie_config_msgs/agnocast_cie_config_msgs/msg/detail/callback_group_info__struct.hpp
                                               6       6   100%   
install/include/agnocast_cie_config_msgs/agnocast_cie_config_msgs/msg/detail/callback_group_info__traits.hpp
                                               2       0     0%   107,109
src/agnocastlib/include/agnocast/agnocast.hpp
                                              17      16    94%   257
src/agnocastlib/include/agnocast/agnocast_callback_info.hpp
                                              31      30    96%   146
src/agnocastlib/include/agnocast/agnocast_epoll.hpp
                                               9       5    55%   44,52,63,65
src/agnocastlib/include/agnocast/agnocast_epoll_event.hpp
                                               6       6   100%   
src/agnocastlib/include/agnocast/agnocast_epoll_update_dispatcher.hpp
                                               7       7   100%   
src/agnocastlib/include/agnocast/agnocast_publisher.hpp
                                              58      47    81%   101,112-113,143,147,149,158-160,222-223
src/agnocastlib/include/agnocast/agnocast_smart_pointer.hpp
                                              97      93    95%   305,310,322,327
src/agnocastlib/include/agnocast/agnocast_subscription.hpp
                                              52       9    17%   98,104,107-110,123,128-132,136,138-139,142-143,145,147-150,152,159,162,164,166-167,170,173-174,184,187,189,191-192,195,198-199,207,215-216,218
src/agnocastlib/include/agnocast/agnocast_timer.hpp
                                              14      11    78%   37,80,96
src/agnocastlib/include/agnocast/agnocast_timer_info.hpp
                                               6       5    83%   82
src/agnocastlib/include/agnocast/agnocast_tracepoint_wrapper.h
                                              13       7    53%   15,32,52,59,70,83
src/agnocastlib/include/agnocast/agnocast_utils.hpp
                                              15       8    53%   20-22,28,32,36,41
src/agnocastlib/include/agnocast/bridge/agnocast_bridge_ipc_event_loop_base.hpp
                                             102       0     0%   51,82,84-85,88-93,97,99,102,104-105,107,109-113,115-116,118-122,124-125,128-130,134,137,139-140,144,146,149,151,154,156,159,162-163,165-167,171,173-175,178-179,182,184-187,189-190,193,195-196,199,202,204-206,208-209,213,215,218-220,222-224,229,232-234,237-238,241,244,246-248,250,253-255,257,260-262,265,267-268
src/agnocastlib/include/agnocast/bridge/agnocast_bridge_node.hpp
                                             121       8     6%   44,46,55,57,78,93,100,102-105,108-110,115,117-121,125,143,151-153,156-158,163-169,171,173-174,177,181,184-185,189,192-193,197,201-204,206-207,210,212-213,216,219-220,222-230,233-234,239,243,246,250-251,253-254,257-260,263-264,266-272,278-280,283-286,288,291,293-295,297-298,302,305,307,309-313,315-316
src/agnocastlib/include/agnocast/bridge/agnocast_bridge_utils.hpp
                                               1       0     0%   21
src/agnocastlib/include/agnocast/bridge/performance/agnocast_performance_bridge_ipc_event_loop.hpp
                                               1       0     0%   14
src/agnocastlib/include/agnocast/bridge/standard/agnocast_standard_bridge_ipc_event_loop.hpp
                                               1       0     0%   14
src/agnocastlib/include/agnocast/cie_client_utils.hpp
                                               2       2   100%   
src/agnocastlib/include/agnocast/message_filters/message_event.hpp
                                              11      11   100%   
src/agnocastlib/include/agnocast/message_filters/parameter_adapter.hpp
                                               6       6   100%   
src/agnocastlib/include/agnocast/message_filters/pass_through.hpp
                                              12      12   100%   
src/agnocastlib/include/agnocast/message_filters/signal1.hpp
                                              22      22   100%   
src/agnocastlib/include/agnocast/message_filters/signal9.hpp
                                              70      65    92%   287,289-292
src/agnocastlib/include/agnocast/message_filters/simple_filter.hpp
                                              10       7    70%   57,59,61
src/agnocastlib/include/agnocast/message_filters/subscriber.hpp
                                              42       0     0%   21,23-25,38,77,81,94,99,155,160,163,167,200,212,216-218,231,235,249,253-255,269,273,275-282,290,292-296,305,330
src/agnocastlib/include/agnocast/message_filters/sync_policies/approximate_time.hpp
                                             363     314    86%   138,148,151,154-155,165,168,170,176,278-300,334-350
src/agnocastlib/include/agnocast/message_filters/sync_policies/exact_time.hpp
                                              61      60    98%   188
src/agnocastlib/include/agnocast/message_filters/synchronizer.hpp
                                             101      92    91%   134,136-137,192,195,197-198,365,367
src/agnocastlib/include/agnocast/node/agnocast_arguments.hpp
                                               3       1    33%   30,32
src/agnocastlib/include/agnocast/node/agnocast_context.hpp
                                               3       1    33%   25,27
src/agnocastlib/include/agnocast/node/agnocast_node.hpp
                                              16      10    62%   75,83,424,428,457,462
src/agnocastlib/include/agnocast/node/node_interfaces/node_base.hpp
                                               1       1   100%   
src/agnocastlib/include/agnocast/node/node_interfaces/node_clock.hpp
                                               1       1   100%   
src/agnocastlib/include/agnocast/node/node_interfaces/node_logging.hpp
                                               1       1   100%   
src/agnocastlib/include/agnocast/node/node_interfaces/node_parameters.hpp
                                               1       1   100%   
src/agnocastlib/include/agnocast/node/node_interfaces/node_services.hpp
                                               1       1   100%   
src/agnocastlib/include/agnocast/node/node_interfaces/node_topics.hpp
                                               1       1   100%   
src/agnocastlib/src/agnocast.cpp             264       5     1%   22,24,53,56,58-64,68-69,72,74-75,77-79,81,83-88,91-96,100-101,105-109,112,115,117,120,122-123,130,132-136,140,142-147,150,152-153,157,159-162,165-169,173,175-176,181-182,185,187,190,192,194-202,205-207,211-212,215,217,219-220,223,225-229,231,235,238,241-247,249-250,253-255,257,267,269-270,273-275,277-278,280-282,284-285,288-289,292-293,296-299,303-304,307-309,311,314,316-317,320,323,325-326,329,332,336-337,340,343,347,349-350,352-353,355,357-359,362-363,369,372-373,378,381,385,387-390,393-395,397-399,405-408,410-411,414-419,422-423,425-426,428-429,431,434-435,438-439,442,446,449-451,454-457,459,461,464-468,471-473,476-480,483-485,488-489,491-494,496-498,501-503,507-510,513-516,523-524
src/agnocastlib/src/agnocast_callback_info.cpp
                                             102      81    79%   46-48,53-56,99,131-132,156,161-163,167-169,188,201-203
src/agnocastlib/src/agnocast_callback_isolated_executor.cpp
                                             253     199    78%   22-24,26,39-41,44-46,49,55,84-87,109,133,153,157,201,203-204,207-208,210-211,213,220-222,224,283,308-310,312,329,333,336-337,345,347-348,350,373,375-376,378,402,413,415,436,439
src/agnocastlib/src/agnocast_client.cpp       36       0     0%   16,18,20-28,31,34,36,38-39,42-43,46,49,52-54,56,58,62,67-68,70-73,75-76,79-80
src/agnocastlib/src/agnocast_component_container.cpp
                                              24       0     0%   7,9-10,13,15,20-22,25,27,30,32-34,36-44,47
src/agnocastlib/src/agnocast_component_container_cie.cpp
                                             129       0     0%   23-24,28,47,49,51-54,56,59-61,93,95,97-98,101-103,105-106,110,113,116-119,121,123-126,128,130,132-133,135,137-138,140,142-143,145,147,149,152,156-157,159,161-165,167-169,172-174,177-178,181-182,185-186,189,191,193-197,200,202-205,208,211,215,217-219,221-224,227-228,231-233,236,241,243-246,249-250,253,256,258,260-261,264-265,270,272-273,276,278,283-285,288,290,292-293,295-301,303
src/agnocastlib/src/agnocast_component_container_mt.cpp
                                              31       0     0%   9,11-12,17,19,24-26,29,31,33-35,38-39,41,44-45,47-49,51-59,62
src/agnocastlib/src/agnocast_epoll.cpp        31      21    67%   20-21,39-42,45,56,59-60
src/agnocastlib/src/agnocast_epoll_event.cpp
                                              35      22    62%   13-14,25,27-29,32-33,35,46,48,57,61
src/agnocastlib/src/agnocast_epoll_update_dispatcher.cpp
                                              36      24    66%   36-37,39,42,44-46,48-49,51,53,66
src/agnocastlib/src/agnocast_executor.cpp
                                              45      44    97%   91
src/agnocastlib/src/agnocast_multi_threaded_executor.cpp
                                              88      61    69%   19,22,36-38,47-49,51-53,55-57,59-61,63-65,69,76-77,86-88,166
src/agnocastlib/src/agnocast_publisher.cpp
                                              85       0     0%   14,16,19,21,24,26-27,30-31,33,36,40,42-51,54,57,62,64-67,70-72,74-77,80,82-87,91,93-95,98,102,104,109,113-114,122-127,131,134-135,139,142,144-149,152,154-155,158,160-161,164,167,169-174,177
src/agnocastlib/src/agnocast_single_threaded_executor.cpp
                                              42      26    61%   20,31-33,37,46-48,71,75-78,81-82,84
src/agnocastlib/src/agnocast_smart_pointer.cpp
                                              10       7    70%   14-16
src/agnocastlib/src/agnocast_subscription.cpp
                                              59       0     0%   7-8,10,13-15,17,20,24-37,40,43,45-50,53,55-56,59,61-62,65,68,72-77,79-82,86-87,89,91,94,97-98,102-103,109,111
src/agnocastlib/src/agnocast_timer.cpp         2       2   100%   
src/agnocastlib/src/agnocast_timer_info.cpp
                                             175      53    30%   26,28,30-32,35,38,40,44-45,49,51,53-55,58,61-63,65,68-71,75,77,79-80,82-84,86,91,94,96-99,104,107-108,120-122,124,126-130,132-137,139-141,150,163-165,173-174,182-186,220-224,229-230,247,251-253,256,258,260,262,265-266,268,271,273-274,277,279,294-295,297-298,301-302,305-308,311,315,318-319,321,323-328,330-332,334,339,342-343,346
src/agnocastlib/src/agnocast_tracepoint_wrapper.c
                                               7       7   100%   
src/agnocastlib/src/agnocast_utils.cpp        52      37    71%   19,82-84,90,92,95,97,100,103,106,108-109,112,114
src/agnocastlib/src/bridge/agnocast_bridge_utils.cpp
                                              99       0     0%   14,16-18,21-22,24-25,27-28,30-31,34-35,38,40-42,44,46,48-50,52-54,57,59-61,63,65,68-71,74,76-80,83-86,89,92,94-98,101-103,106,109,111-112,115,117-119,121-123,125,128,130-131,134,136-138,140-142,144,147,149-150,153-155,157-160,163,165-166,169-171,173-176
src/agnocastlib/src/bridge/performance/agnocast_performance_bridge_ipc_event_loop.cpp
                                               3       0     0%   12,16,22
src/agnocastlib/src/bridge/performance/agnocast_performance_bridge_loader.cpp
                                              74       0     0%   14,18,20-22,25,28,32-34,37-38,41,45-47,50-51,54,56-58,61,64-65,68-80,87-89,93,96,98-100,103,105-106,110-113,118-120,122,125,128,131-132,134-136,139-140,142-144,147,150-151,156,159
src/agnocastlib/src/bridge/performance/agnocast_performance_bridge_manager.cpp
                                             183       0     0%   20-23,25-26,29-31,34,36-37,40-41,44-45,49,51,53-54,56,58-59,61-64,67-70,74,76-77,82-83,85,87-90,92-93,95,98,100,102-105,109,112,114-116,118,120,123,125-126,128-130,134,136-138,140-142,146,148-149,151-152,154,159,161-167,170-171,173-174,177-179,181,183-184,187,191-197,200-201,203-204,207-209,211,213-214,217,222,224-226,228,230-231,233,238,240-243,246-247,251,254-256,259-261,264,266-267,270-272,275,278,282-283,286-290,293-294,298,300-303,305-306,309-312,315,317-318,321,325-326,329-331,334,338,341-343,348-349,351,353-355
src/agnocastlib/src/bridge/standard/agnocast_standard_bridge_ipc_event_loop.cpp
                                               3       0     0%   13,17,23
src/agnocastlib/src/bridge/standard/agnocast_standard_bridge_loader.cpp
                                              85       0     0%   18,22,24,27,31,33-35,38,41,44,49-51,54,57-58,61-62,64-66,70,73,75-76,78,81-82,85-88,90,93,96,98,104-107,109-111,113,117-119,121,124-125,127-128,130,133,137-140,142-143,145-146,148,151,154-155,157,160,162-164,167-169,171-174,176-178,180-181,185
src/agnocastlib/src/bridge/standard/agnocast_standard_bridge_manager.cpp
                                             239       0     0%   16-20,22-23,26-28,31,33-34,36,38-40,42-43,48-50,52-53,57,59,61-62,64,66-67,69-71,74-77,81,83-84,89-90,92,94-97,99-100,102,105,107-110,112,116,118-119,121-123,127,131-133,136-138,141,144,147-148,150,152,154-155,158,161,163,166-167,169-170,176,178-180,182-183,187-188,190,192-195,197-198,201-203,207-208,212,214,216-217,220,224,226,228-230,233,236-237,240-241,244,247,250-251,254,257-260,262-265,269-270,272-274,276,278,280-282,284,286-288,292,295-301,303-305,308-315,319-323,326,329,331-332,334-336,340,342-347,350-352,354-355,357,359-361,365-369,377-379,383,386-390,392,395-396,403,405-407,410-411,415-416,418-419,422-424,427-429,433,435-437,439-441,446,450,452-453,455
src/agnocastlib/src/cie_client_utils.cpp      63      47    74%   28,41-43,100,102,105,107-108,113-114,127,132-135
src/agnocastlib/src/node/agnocast_arguments.cpp
                                              76      37    48%   29,31,36,38,41,43-46,48,51-52,54-58,63,65-72,76,88,94-95,124,126-127,131,133-135,139,145
src/agnocastlib/src/node/agnocast_context.cpp
                                              27       0     0%   15,17-18,22-25,28,32-36,38,41-42,45,47-48,51,53-55,61-63,65
src/agnocastlib/src/node/agnocast_node.cpp
                                              19      19   100%   
src/agnocastlib/src/node/agnocast_only_callback_isolated_executor.cpp
                                             131       0     0%   17-18,22,24-27,32,34-37,40,44,47,50-53,56-58,61,65-68,71-74,76,78,80-81,85,87-89,92-93,95,97-100,103-104,107-109,112-114,116-117,119,122,124-126,128,131-132,137,140-144,147-152,154,158-159,162-164,166-168,170,178,180-183,186-188,190-192,197,200-201,203-207,212,217,221-222,224-225,228-229,232-233,237-239,241-242,246,249-251,253-254,256-258,262,265
src/agnocastlib/src/node/agnocast_only_executor.cpp
                                             202       0     0%   18-22,24-31,33,35-37,40-43,46-47,50,53,55-58,61,63-66,69,71-74,77,80-81,84,87,89-90,93,95-96,100,103,106,108-111,114-117,120-121,123,126,130,132,134-135,139,141-144,148,156-160,162,164-168,171-173,176,182,187-193,195-198,200-201,204,206-212,214-215,217,221,223-227,229,233,235-239,241,244,247-251,253-255,258,260-269,271-273,276,281,286,292-294,297-298,300-306,308-310,313,318-319,322,324,327,333-336,339,341-345,347,350-353,356-361,363-365,369,372,374
src/agnocastlib/src/node/agnocast_only_multi_threaded_executor.cpp
                                              39       0     0%   10-16,18,23,25-28,31,33,35-37,40,42-43,47,49-53,57,59-60,66-70,73,76-78
src/agnocastlib/src/node/agnocast_only_single_threaded_executor.cpp
                                              24       0     0%   8-9,11-13,19,24,26-29,32,34-38,42-46,49-50
src/agnocastlib/src/node/agnocast_signal_handler.cpp
                                              41       0     0%   23,25-26,30-31,34,37-38,40-42,45-47,51,53-54,56-59,63-65,67-68,71,73-78,83,86,89,91-95
src/agnocastlib/src/node/node_interfaces/node_base.cpp
                                             177     104    58%   33,42,56-58,61-62,74-76,79-80,124,126,129,131,133,136,138,140,143,145,147,150,152,154,181,187,189-190,198,200,202-205,208,222,224,231,233,238,242,247,250,254,269-272,274,283-284,286,299-301,304-305,308-309,321-325,339-343,345,353
src/agnocastlib/src/node/node_interfaces/node_clock.cpp
                                               7       5    71%   16,18
src/agnocastlib/src/node/node_interfaces/node_logging.cpp
                                               6       2    33%   12,14,17,19
src/agnocastlib/src/node/node_interfaces/node_parameters.cpp
                                             395      88    22%   37-41,43,45,57,61-66,68,70-71,73,85,90-91,99-100,111-113,115-116,125,127,130,132-134,143-146,148-151,153-154,156-157,159-161,165-168,170-173,175-176,178-180,182-184,189,192,196-197,211-213,216,229-230,234,249,255,283,289-291,293,295-298,308,320,322-324,339,360,364-365,367-369,372-373,375,378-380,383,385-386,388-391,394-396,398-400,403,413,416-417,419-421,424,427,430-431,433,439-441,444-445,449-450,452,454,457,460-461,465-468,476-477,480-482,485,487,489-490,493,500-506,509,511,514-519,521,527-535,537,543,547,549-550,553-554,558,560,562,565,569-570,572-573,575,584,587,590-591,593-595,597,600,602,604,607,609,611-616,618,621,624,626-627,629,632-634,638,641,644-646,648-657,663-664,667,670,673-675,677-682,684,690-691,694,697,700-701,703,705-707,710,712-716,718-720,722-724,726-727,729,732-733,738-745,749,756,759-760,762-763,765-766,769,772-773,775,777-779,781,785,788
src/agnocastlib/src/node/node_interfaces/node_services.cpp
                                              10       2    20%   12,17-18,21,26,28,31,33
src/agnocastlib/src/node/node_interfaces/node_time_source.cpp
                                              98      48    49%   49,53-54,57,60,81,92,94,96,100,103-104,115,118-119,125,132-134,137-139,145,149,151-152,154,157-158,163,165,167-168,172,175-179,183-186,193-195,200,202-203,206
src/agnocastlib/src/node/node_interfaces/node_topics.cpp
                                              21       4    19%   18,20,23,30,32,35,40,42,45,52,54,57,62,64,67,69,71
------------------------------------------------------------------------------
TOTAL                                       4815    1812    37%
------------------------------------------------------------------------------

ruth561 added 2 commits April 10, 2026 09:14
Signed-off-by: Takumi Jin <primenumber_2_3_5@yahoo.co.jp>
Signed-off-by: Takumi Jin <primenumber_2_3_5@yahoo.co.jp>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 8 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 34 to 40
while (spinning_.load()) {
if (need_epoll_updates.load()) {
if (epoll_update_tracker_.need_update()) {
add_callback_groups_from_nodes_associated_to_executor();
agnocast::prepare_epoll_impl(
epoll_fd_, my_pid_, ready_agnocast_executables_mutex_, ready_agnocast_executables_,
[this](const rclcpp::CallbackGroup::SharedPtr & group) {
return is_callback_group_associated(group);
});
epoll_manager_->prepare_epoll([this](const rclcpp::CallbackGroup::SharedPtr & group) {
return is_callback_group_associated(group);
});
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

epoll_update_tracker_.need_update() is edge-triggered (it clears the flag via exchange). If prepare_epoll() skips registrations because is_callback_group_associated(group) is false (e.g., subscription/timer created before the node/callback group is added/associated), the corresponding need_epoll_update flags stay true but this loop won’t call prepare_epoll() again unless some unrelated notify_all() happens. This can leave fds permanently unregistered in this executor’s epoll set. Consider re-notifying (or keeping this executor’s tracker flagged) while there are pending need_epoll_update entries, and/or triggering an epoll-update notification from add_node/callback-group association changes.

Copilot uses AI. Check for mistakes.
Comment on lines 49 to 55
while (spinning_.load()) {
if (need_epoll_updates.load()) {
if (epoll_update_tracker_.need_update()) {
add_callback_groups_from_nodes_associated_to_executor();
agnocast::prepare_epoll_impl(
epoll_fd_, my_pid_, ready_agnocast_executables_mutex_, ready_agnocast_executables_,
[this](const rclcpp::CallbackGroup::SharedPtr & group) {
return is_callback_group_associated(group);
});
epoll_manager_->prepare_epoll([this](const rclcpp::CallbackGroup::SharedPtr & group) {
return is_callback_group_associated(group);
});
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same edge-trigger issue as the single-threaded version: if prepare_epoll() skips entries because callback groups are not yet associated, need_epoll_update remains true but epoll_update_tracker_ is cleared, so later association (e.g., add_node() after subscription creation) won’t cause another prepare_epoll() call. This can strand subscriptions/timers unregistered. Consider keeping the tracker flagged until pending updates are resolved, or notify on node/callback-group association changes.

Copilot uses AI. Check for mistakes.
Comment on lines 719 to 750
TEST(AllocateCallbackInfoIdTest, throws_when_id_has_reserved_epoll_flag_bits)
{
// Arrange: Set next_callback_info_id so the next allocation hits SHUTDOWN_EVENT_FLAG (bit 29).
const uint32_t original = next_callback_info_id.load();
next_callback_info_id.store(SHUTDOWN_EVENT_FLAG);
next_callback_info_id.store(MAX_CALLBACK_INFO_ID);

// Act & Assert
EXPECT_THROW(allocate_callback_info_id(), std::runtime_error);

// Cleanup
next_callback_info_id.store(original);
}

TEST(AllocateCallbackInfoIdTest, succeeds_just_below_reserved_range)
{
// Arrange: Set next_callback_info_id to the maximum valid value (one below SHUTDOWN_EVENT_FLAG).
const uint32_t original = next_callback_info_id.load();
next_callback_info_id.store(SHUTDOWN_EVENT_FLAG - 1);
next_callback_info_id.store(MAX_CALLBACK_INFO_ID - 1);

// Act & Assert
EXPECT_EQ(allocate_callback_info_id(), SHUTDOWN_EVENT_FLAG - 1);
EXPECT_EQ(allocate_callback_info_id(), MAX_CALLBACK_INFO_ID - 1);

// Cleanup
next_callback_info_id.store(original);
}

TEST(AllocateTimerIdTest, throws_when_id_has_reserved_epoll_flag_bits)
{
// Arrange: Set next_timer_id so the returned ID includes a reserved epoll flag bit.
// This covers the bug where timer IDs OR'd with CLOCK_EVENT_FLAG/TIMER_EVENT_FLAG
// could collide with reserved flags.
const uint32_t original = next_timer_id.load();
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These test comments still refer to the old epoll-flag-bit scheme (SHUTDOWN_EVENT_FLAG, CLOCK_EVENT_FLAG, TIMER_EVENT_FLAG). After the refactor to MAX_*_ID limits / packed epoll data, the wording is misleading. Update the comments to describe the new overflow boundary being tested (MAX_*_ID) to keep the tests self-explanatory.

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 15
{

constexpr uint32_t MAX_CALLBACK_INFO_ID = 0x10000000;

struct AgnocastExecutable;
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_CALLBACK_INFO_ID is now hardcoded to 0x10000000, which is a stricter limit than the previous reserved-bit boundary and no longer obviously required since epoll data is now packed into a u64 (type in upper 32 bits, id in lower 32). If there’s no remaining bit-level constraint, consider raising this to the previous limit (or to UINT32_MAX-based overflow detection) and/or document why 0x10000000 is the intended cap to avoid an unintended capacity regression.

Copilot uses AI. Check for mistakes.
Comment on lines 17 to 22

constexpr int64_t NANOSECONDS_PER_SECOND = 1000000000;
constexpr uint32_t MAX_TIMER_ID = 0x10000000;

struct AgnocastExecutable;

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAX_TIMER_ID is hardcoded to 0x10000000. With the new u64 epoll data packing, timer IDs no longer need to avoid top-bit flag collisions. Unless there’s a separate constraint, this lowers the maximum number of timers compared to the prior reserved-bit scheme. Consider using a UINT32_MAX-style overflow check (or documenting the rationale for 0x10000000) to avoid an accidental capacity regression.

Copilot uses AI. Check for mistakes.
Comment on lines +66 to +69
if (!results.empty()) {
return -1;
}

Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Epoll::wait() returns -1 if the caller passes a non-empty results vector, but it doesn’t set errno in that path. Since callers (e.g., EpollManager) interpret -1 using errno, this can lead to misleading error handling. Consider always clearing results (or explicitly setting errno = EINVAL / documenting the precondition) rather than treating non-empty input as an error silently.

Suggested change
if (!results.empty()) {
return -1;
}

Copilot uses AI. Check for mistakes.
Comment on lines +18 to +22
for (uint32_t type = 0; type < static_cast<size_t>(EpollEventType::NrEventType); type++) {
if (!sources_[type]) {
RCLCPP_ERROR(logger, "invalid epoll event source array: sources_[%d] is nullptr", type);
exit(EXIT_FAILURE);
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RCLCPP_ERROR(logger, "... sources_[%d] ...", type) uses %d but type is uint32_t. With printf-style formatting this is undefined behavior / can trigger -Wformat warnings. Use %u (or cast type to int if you really want signed).

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +60
if (EpollEventType::NrEventType <= event_type) {
RCLCPP_ERROR(
logger, "Agnocast internal implementation error: invalid epoll event type %d",
static_cast<uint32_t>(event_type));
close(agnocast_fd);
exit(EXIT_FAILURE);
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RCLCPP_ERROR(logger, "... invalid epoll event type %d", static_cast<uint32_t>(event_type)) uses %d but passes an unsigned value. This is a format/argument type mismatch (potential UB, -Wformat). Prefer %u (or cast to int and keep %d).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

need-patch-update Bug fixes and other changes - requires PATCH version update run-build-test Run build-test in CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Refactor epoll event handling and flag management

2 participants