Skip to content

Commit 30061c6

Browse files
Fix parallel deletion (#1858)
1 parent 2ebbece commit 30061c6

File tree

2 files changed

+44
-8
lines changed

2 files changed

+44
-8
lines changed

include/openPMD/auxiliary/Filesystem.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121
#pragma once
2222

23+
#include <optional>
2324
#include <string>
2425
#include <vector>
2526

@@ -66,6 +67,19 @@ namespace auxiliary
6667
*/
6768
std::vector<std::string> list_directory(std::string const &path);
6869

70+
/** List all contents of a directory at a given absolute or relative path.
71+
*
72+
* @note The equivalent of `ls path`
73+
* @note Both contained files and directories are listed.
74+
* `.` and `..` are not returned.
75+
* @param path Absolute or relative path of directory to examine.
76+
* @return Vector of all contained files and directories,
77+
* or an empty option in case of an IO error, in which case the
78+
* specific error will be stored in errno.
79+
*/
80+
std::optional<std::vector<std::string>>
81+
list_directory_nothrow(std::string const &path);
82+
6983
/** Create all required directories to have a reachable given absolute or
7084
* relative path.
7185
*

src/auxiliary/Filesystem.cpp

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ bool file_exists(std::string const &path)
6767
}
6868

6969
std::vector<std::string> list_directory(std::string const &path)
70+
{
71+
auto res = list_directory_nothrow(path);
72+
if (!res)
73+
{
74+
throw std::system_error(std::error_code(errno, std::system_category()));
75+
}
76+
else
77+
{
78+
return *res;
79+
}
80+
}
81+
82+
std::optional<std::vector<std::string>>
83+
list_directory_nothrow(std::string const &path)
7084
{
7185
std::vector<std::string> ret;
7286
#ifdef _WIN32
@@ -86,7 +100,9 @@ std::vector<std::string> list_directory(std::string const &path)
86100
#else
87101
auto directory = opendir(path.c_str());
88102
if (!directory)
89-
throw std::system_error(std::error_code(errno, std::system_category()));
103+
{
104+
return std::nullopt;
105+
}
90106
dirent *entry;
91107
while ((entry = readdir(directory)) != nullptr)
92108
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
@@ -150,14 +166,20 @@ bool remove_directory(std::string const &path)
150166
return (0 == remove(p.c_str()));
151167
};
152168
#endif
153-
for (auto const &entry : list_directory(path))
169+
auto entries = list_directory_nothrow(path);
170+
// Check if some other process was faster deleting this
171+
if (entries)
154172
{
155-
auto partialPath = path;
156-
partialPath.append(std::string(1, directory_separator)).append(entry);
157-
if (directory_exists(partialPath))
158-
success &= remove_directory(partialPath);
159-
else if (file_exists(partialPath))
160-
success &= remove_file(partialPath);
173+
for (auto const &entry : *entries)
174+
{
175+
auto partialPath = path;
176+
partialPath.append(std::string(1, directory_separator))
177+
.append(entry);
178+
if (directory_exists(partialPath))
179+
success &= remove_directory(partialPath);
180+
else if (file_exists(partialPath))
181+
success &= remove_file(partialPath);
182+
}
161183
}
162184
success &= del(path);
163185
return success;

0 commit comments

Comments
 (0)