Skip to content

Fix EventManager RTTI failures across shared-library boundaries#3459

Open
taylorhoward92 wants to merge 8 commits intogazebosim:mainfrom
taylorhoward92:fix/eventmanager-rtti-across-dylibs
Open

Fix EventManager RTTI failures across shared-library boundaries#3459
taylorhoward92 wants to merge 8 commits intogazebosim:mainfrom
taylorhoward92:fix/eventmanager-rtti-across-dylibs

Conversation

@taylorhoward92
Copy link
Copy Markdown
Contributor

@taylorhoward92 taylorhoward92 commented Apr 7, 2026

🦟 Bug fix

Fixes #1992

Summary

When plugins are loaded with RTLD_LOCAL and built with hidden visibility (the default via gz-cmake), each dylib gets its own copy of the RTTI type_info for the same C++ type. This causes dynamic_cast to return nullptr in EventManager::Connect, Emit, and ConnectionCount even though the object really is the requested type. It also causes typeid(E).hash_code() and operator== on type_info references to disagree across dylib boundaries, creating duplicate map entries.

This is the root cause of the issues described in #1992.

Changes

  • Replace dynamic_cast with static_cast in Connect(), Emit(), and ConnectionCount(). The map key already guarantees the correct type by construction.
  • Switch Hasher to name-based hashing via std::hash<std::string>(typeid::name()).
  • Add a name-based fallback in EqualTo so that the same type loaded from different shared libraries compares equal.

Checklist

  • Signed all commits for DCO
  • Added a screen capture or video to the PR description that demonstrates the fix (as needed)
  • Added tests
  • Updated documentation (as needed)
  • Updated migration guide (as needed)
  • Consider updating Python bindings (if the library has them)
  • codecheck passed (See contributing)
  • All tests passed (See test coverage)
  • Updated Bazel files (if adding new files). Created an issue otherwise.
  • While waiting for a review on your PR, please help review another open pull request to support the maintainers
  • Was GenAI used to generate this PR? If so, make sure to add "Generated-by" to your commits. (See this policy for more info.)

Generated-by: Claude Code

Note to maintainers: Remember to use Squash-Merge and edit the commit message to match the pull request summary while retaining Signed-off-by and Generated-by messages.

@taylorhoward92 taylorhoward92 changed the base branch from main to gz-sim10 April 7, 2026 10:46
@taylorhoward92 taylorhoward92 changed the base branch from gz-sim10 to main April 7, 2026 10:50
@taylorhoward92 taylorhoward92 marked this pull request as ready for review April 7, 2026 11:09
@taylorhoward92 taylorhoward92 requested a review from arjo129 as a code owner April 7, 2026 11:09
When plugins are loaded with RTLD_LOCAL and built with hidden
visibility (the default via gz-cmake), each dylib gets its own
copy of the RTTI type_info for the same C++ type.  This causes
three problems in EventManager:

1. dynamic_cast across the boundary returns nullptr even though
   the object really is the requested type.
2. typeid(E).hash_code() returns different values for the same
   type in different dylibs, so the unordered_map creates
   duplicate entries.
3. operator== on type_info references compares pointer identity,
   which also differs across dylibs.

Fix by:
- Replacing dynamic_cast with static_cast (the map key already
  guarantees the correct type by construction).
- Switching the Hasher to name-based hashing via
  std::hash<std::string>(typeid::name()).
- Adding a name-based fallback in EqualTo so that the same type
  loaded from different shared libraries compares equal.

Signed-off-by: Taylor Howard <taylor.howard@absiko.com.au>
@taylorhoward92 taylorhoward92 force-pushed the fix/eventmanager-rtti-across-dylibs branch from 8a02996 to 6b1df76 Compare April 8, 2026 10:26
Taylor Howard and others added 2 commits April 9, 2026 12:25
The Hasher functor uses std::hash<std::string> but <string> was not
included, causing a cpplint include_what_you_use failure.

Generated-by: Claude Code
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Taylor Howard <taylor.howard@absiko.com.au>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Inbox

Development

Successfully merging this pull request may close these issues.

EventManager use of typeid to index events may have undefined behaviour in plugins

2 participants