From 7d3413944d5d2b2c8788c8bc3c5da99ea4711b5b Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Fri, 19 Dec 2025 21:58:18 -0800 Subject: [PATCH] Improve exception safety in get_or_create_call_once_storage_map() Use std::unique_ptr to hold the newly allocated storage map until the capsule is successfully created. This prevents a memory leak if capsule creation throws an exception. --- include/pybind11/gil_safe_call_once.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/include/pybind11/gil_safe_call_once.h b/include/pybind11/gil_safe_call_once.h index 083018f95..b68dd26e6 100644 --- a/include/pybind11/gil_safe_call_once.h +++ b/include/pybind11/gil_safe_call_once.h @@ -13,6 +13,7 @@ # include #endif #ifdef PYBIND11_HAS_SUBINTERPRETER_SUPPORT +# include # include #endif @@ -254,17 +255,22 @@ private: } storage_map = reinterpret_cast(raw_ptr); } else { - storage_map = new call_once_storage_map_type(); + // Use unique_ptr for exception safety: if capsule creation throws, + // the map is automatically deleted. + auto storage_map_ptr = std::unique_ptr( + new call_once_storage_map_type()); // Create capsule with destructor to clean up the storage map when the interpreter // shuts down state_dict[PYBIND11_CALL_ONCE_STORAGE_MAP_ID] - = capsule(storage_map, [](void *ptr) noexcept { + = capsule(storage_map_ptr.get(), [](void *ptr) noexcept { auto *map = reinterpret_cast(ptr); for (const auto &entry : *map) { delete entry.second; } delete map; }); + // Capsule now owns the storage map, release from unique_ptr + storage_map = storage_map_ptr.release(); } return storage_map; }