| Bug #120342 | register_service_nolock() leaves stale interface_mapping entry if default-name map insertion throws | ||
|---|---|---|---|
| Submitted: | 25 Apr 9:01 | Modified: | 4 May 5:40 |
| Reporter: | S F. | Email Updates: | |
| Status: | Documenting | Impact on me: | |
| Category: | MySQL Server: Components / Services | Severity: | S3 (Non-critical) |
| Version: | MySQL Server trunk @ 447eb26e094b444a88c | OS: | Ubuntu (Linux 5.4.0-216-generic) |
| Assigned to: | CPU Architecture: | x86 (x86_64) | |
| Tags: | components, dangling-pointer, exception-safety, libminchassis, registry | ||
[4 May 5:40]
Miroslav Rajcic
Thank you for the report.
[28 May 1:13]
MySQL Admin
Posted by developer: Bug status updated to 'Documenting'

Description: mysql_registry_no_lock_imp::register_service_nolock() publishes imp.get() into service_registry and interface_mapping before ownership is released. Relevant sequence: 1. service_registry.emplace(imp->name_c_str(), imp.get()) 2. interface_mapping.emplace(imp->interface(), imp.get()) 3. service_registry.emplace_hint(addition_result.first, imp->service_name_c_str(), imp.get()) If step 3 throws, the catch only erases the first service_registry entry. The unique_ptr then destroys mysql_service_implementation, but interface_mapping still contains the freed pointer. The stale pointer can later be dereferenced during component unload: dynamic_loader.cc:1338 calls mysql_registry_imp::get_service_implementation_reference_count(...) which reaches registry_no_lock.cc:82: return iter->second->get_reference_count(); How to repeat: I do not currently have a deterministic in-tree trigger without allocation fault injection. The realistic throw point is std::bad_alloc during the second service_registry insertion. Suggested fix: Either delay interface_mapping publication until all service_registry insertions succeed, or roll back the interface_mapping entry in the catch path before imp is destroyed.