Skip to content

hardening: align Logger and ConfigWatcher leak-on-purpose paths to nothrow pattern #75

Description

@coderabbitai

Follow-up hardening pass (post-3.2.0)

Context

PR #74 (chore: bump version to 3.2.0) ships two noexcept destructor paths that intentionally leak objects into a static container to avoid loader-lock / static-destruction-order hazards:

  • Logger::shutdown_internal — appends to a static vector under loader lock.
  • ~ConfigWatcher (loader-lock detach branch) — uses s_leaked_impls.emplace_back(std::move(impl_)) inside the noexcept destructor.

Both are currently safe in practice (the branch fires at most once per instance during DLL unload, where an OOM-induced terminate is indistinguishable from OS teardown), but std::vector::emplace_back can in principle throw bad_alloc, which under a noexcept destructor would call std::terminate.

Goal

Align both paths with the HookManager pattern introduced in PR #71:

  • Use new (std::nothrow) + release() instead of emplace_back so the noexcept contract is honestly honoured even under OOM.
  • Keep the approach consistent across all three components.

Why deferred

The HookManager pattern was forced by a different constraint (unordered_map holding move-only safetyhook::VmtHook values interacting with MSVC's noexcept destructor check). That constraint does not apply to std::vector<std::unique_ptr<Impl>>, so the change is low-risk but should be done as a single consistent pass covering both Logger and ConfigWatcher rather than piecemeal.

References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions