aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libnvxx/nv_list.cc42
1 files changed, 21 insertions, 21 deletions
diff --git a/libnvxx/nv_list.cc b/libnvxx/nv_list.cc
index 72fc937..6bcfd7e 100644
--- a/libnvxx/nv_list.cc
+++ b/libnvxx/nv_list.cc
@@ -806,29 +806,29 @@ __nv_list::take_descriptor_array(std::string_view key)
{
__throw_if_error();
- // define this here to avoid throwing after we call
- // nvlist_take_descriptor_array().
- auto ret = std::vector<nv_fd>{};
+ /*
+ * don't use nvlist_take_descriptor_array() here, because we don't
+ * want to remove the array from the nvlist if vector allocation fails.
+ */
+
+ auto skey = std::string(key);
auto nitems = std::size_t{};
- auto ptr = __ptr_guard(
- ::nvlist_take_descriptor_array(__m_nv,
- std::string(key).c_str(),
- &nitems));
- auto fds = std::span(ptr.__ptr, ptr.__ptr + nitems);
-
- try {
- ret.reserve(fds.size());
- for (auto fd : fds)
- ret.push_back(nv_fd(fd));
-
- return ret;
- } catch (...) {
- // close all the fds we didn't manage to add to the vector
- for (auto fd : fds.subspan(ret.size()))
- (void)::close(fd);
- throw;
- }
+ auto ptr = ::nvlist_get_descriptor_array(__m_nv, skey.c_str(), &nitems);
+ auto fds = std::span(ptr, ptr + nitems);
+
+ /*
+ * reserve space before copying since creating an nv_fd will take
+ * ownership of the fd, and we don't want to partially close the fds
+ * if allocation fails.
+ */
+ auto ret = std::vector<nv_fd>{};
+ ret.reserve(fds.size());
+
+ std::ranges::copy(fds | construct<nv_fd>, std::back_inserter(ret));
+
+ ::nvlist_free_descriptor_array(__m_nv, skey.c_str());
+ return ret;
}
/*