Skip to content

Add type hash to names_and_types (#356)#421

Open
tisomi wants to merge 1 commit into
ros2:rollingfrom
tisomi:rolling
Open

Add type hash to names_and_types (#356)#421
tisomi wants to merge 1 commit into
ros2:rollingfrom
tisomi:rolling

Conversation

@tisomi

@tisomi tisomi commented Jul 2, 2026

Copy link
Copy Markdown

Description

This PR extends rmw_names_and_types_t with a type_hashes parallel array, so the
ROS graph query APIs (rmw_get_topic_names_and_types, rmw_get_service_names_and_types,
and the per-node variants) can expose the type hash of each name/type pair alongside the
existing names and types arrays. The new array is indexed in lockstep with the others:
type_hashes[i][j] corresponds to types[i].data[j].

Alongside the struct change, the lifecycle helpers were updated and hardened:

  • rmw_names_and_types_init now enforces the documented zero-initialized precondition on
    its output argument, returning RMW_RET_INVALID_ARGUMENT when it is not zero-initialized.
    Previously the precondition was documented but unchecked, so passing a populated struct
    would silently leak. It also allocates and unwinds the new type_hashes array, restoring
    the struct to the zero state on any allocation failure so the caller can re-init without
    leaking.
  • rmw_names_and_types_fini now cleans up the type_hashes array and finalizes partially-initialized structs — e.g. one left by a middleware
    populate that inits the full struct then fails mid-fill — freeing the new type_hashes
    array row-by-row (skipping rows still NULL) instead of leaking it. The unconditional
    names cleanup is a no-op on a zero-initialized names array.

Updated the doxygen across the affected headers to mention type hashes.

New fault-injection tests cover the type_hashes allocation-failure path and assert the
output struct is restored to the zero state after RMW_RET_BAD_ALLOC, so the caller can
re-init without leaks.

Note: this extends a public struct and is therefore an ABI break.

This is the interface half of the change; populating the field is handled in the companion
middleware PRs (see Additional Information).

Related: Issue #356

Is this user-facing behavior change?

Yes.

  • rmw_names_and_types_t gains a type_hashes member — an ABI break; downstream consumers
    must be rebuilt against the new layout.
  • Once paired with the middleware PRs, the graph query APIs report the type hash of each
    name/type pair.
  • rmw_names_and_types_init now rejects a non-zero-initialized output argument with
    RMW_RET_INVALID_ARGUMENT. Callers that already follow the documented contract (passing a
    struct from rmw_get_zero_initialized_names_and_types()) are unaffected; callers that
    relied on the previous unchecked behavior get an explicit error instead of a silent leak.

Did you use Generative AI?

Yes. Claude (claude-sonnet-4-6) via GitHub Copilot was used to explore the codebase and
create an initial prototype.

Additional Information

  • Companion PRs completing the feature:
  • The new header include (rosidl_runtime_c/type_hash.h) needs no packaging change:
    rosidl_runtime_c is already a build/build_export dependency of this package.

Testing

  • Ran the package unit tests (including the new fault-injection cases) in a Docker
    container; all pass.
  • Implemented and successfully ran an integration test exercising the end-to-end
    type-hash path through the graph query APIs.

This is a SIEMENS activity and was initialized by @gramss

Extends rmw_names_and_types_t with a type_hashes parallel array so the
graph query APIs expose the type hash of each name/type pair, alongside
the existing names and types arrays. `type_hashes[i][j]` corresponds to
`types[i].data[j]`.

rmw_names_and_types_init now enforces the documented zero-initialized
precondition on its output argument and returns RMW_RET_INVALID_ARGUMENT
otherwise. Adds fault-injection tests for the new field and pins down
that the output struct is restored to zero state after a BAD_ALLOC, so
the caller can re-init without leaks.

Updates the doxygen across the affected headers so the descriptive
prose says "names, types, and type hashes" instead of repeating the
snake_case identifier outside code references, and documents the
no-op-on-zero behavior of the unconditional cleanup in
rmw_names_and_types_fini (which now correctly cleans up
partially-initialized structs that the previous code leaked).

Note: this extends a public struct and is therefore an ABI break.

Signed-off-by: tisomi <titus090404@gmail.com>
@mergify

mergify Bot commented Jul 2, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@wjwwood wjwwood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I believe we should change the interface to allow representation of mismatched types, since this is an introspection interface, it should be possible to see what types and hashes there are, even when there is a mismatch (perhaps especially in that case).

Comment on lines +40 to +43

/// Array of arrays of type hashes, with the same length as `names`.
/// `type_hashes[i][j]` corresponds to `types[i].data[j]`.
rosidl_type_hash_t ** type_hashes;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In my opinion, we should have an array of type hashes for each type, so that when there is an incompatability (mismatched type hashes) it can be represented on the graph. If you have this issue in the graph right now, you can see each end-point's type and type hash, so it would be weird that this interface cannot reflect the same situation.

It's fine if we have warnings about this kind of thing, but I would prefer to see those warnings produced in rcl rather than in each middleware (for consistency), instead it would be better to have the middleware represent the reality of the graph (correct or not) and then notifying the rcl layer when the graph changes or when there is an incompatibility so that the rcl layer can produce the warning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants