From cc335050727ccb48b0891a4c9800382d6de0a412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20P=C3=B6schel?= Date: Tue, 3 Mar 2026 11:43:08 +0100 Subject: [PATCH] Fix parallel deletion --- include/openPMD/auxiliary/Filesystem.hpp | 14 +++++++++ src/auxiliary/Filesystem.cpp | 38 +++++++++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/include/openPMD/auxiliary/Filesystem.hpp b/include/openPMD/auxiliary/Filesystem.hpp index 25239f65a3..6ad0288a5f 100644 --- a/include/openPMD/auxiliary/Filesystem.hpp +++ b/include/openPMD/auxiliary/Filesystem.hpp @@ -20,6 +20,7 @@ */ #pragma once +#include #include #include @@ -66,6 +67,19 @@ namespace auxiliary */ std::vector list_directory(std::string const &path); + /** List all contents of a directory at a given absolute or relative path. + * + * @note The equivalent of `ls path` + * @note Both contained files and directories are listed. + * `.` and `..` are not returned. + * @param path Absolute or relative path of directory to examine. + * @return Vector of all contained files and directories, + * or an empty option in case of an IO error, in which case the + * specific error will be stored in errno. + */ + std::optional> + list_directory_nothrow(std::string const &path); + /** Create all required directories to have a reachable given absolute or * relative path. * diff --git a/src/auxiliary/Filesystem.cpp b/src/auxiliary/Filesystem.cpp index 2a3e947a9e..3c70722344 100644 --- a/src/auxiliary/Filesystem.cpp +++ b/src/auxiliary/Filesystem.cpp @@ -67,6 +67,20 @@ bool file_exists(std::string const &path) } std::vector list_directory(std::string const &path) +{ + auto res = list_directory_nothrow(path); + if (!res) + { + throw std::system_error(std::error_code(errno, std::system_category())); + } + else + { + return *res; + } +} + +std::optional> +list_directory_nothrow(std::string const &path) { std::vector ret; #ifdef _WIN32 @@ -86,7 +100,9 @@ std::vector list_directory(std::string const &path) #else auto directory = opendir(path.c_str()); if (!directory) - throw std::system_error(std::error_code(errno, std::system_category())); + { + return std::nullopt; + } dirent *entry; while ((entry = readdir(directory)) != nullptr) if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) @@ -150,14 +166,20 @@ bool remove_directory(std::string const &path) return (0 == remove(p.c_str())); }; #endif - for (auto const &entry : list_directory(path)) + auto entries = list_directory_nothrow(path); + // Check if some other process was faster deleting this + if (entries) { - auto partialPath = path; - partialPath.append(std::string(1, directory_separator)).append(entry); - if (directory_exists(partialPath)) - success &= remove_directory(partialPath); - else if (file_exists(partialPath)) - success &= remove_file(partialPath); + for (auto const &entry : *entries) + { + auto partialPath = path; + partialPath.append(std::string(1, directory_separator)) + .append(entry); + if (directory_exists(partialPath)) + success &= remove_directory(partialPath); + else if (file_exists(partialPath)) + success &= remove_file(partialPath); + } } success &= del(path); return success;