New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add retry to storagePosixPathRemove(). #1786
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -433,6 +433,17 @@ storagePosixPathRemoveCallback(void *const callbackData, const StorageInfo *cons | |
FUNCTION_TEST_RETURN_VOID(); | ||
} | ||
|
||
// Helper to determine if an error code indicates that a path is not empty. This can vary by implementation. | ||
static bool | ||
storagePosixErrorIsEmpty(const int error) | ||
{ | ||
FUNCTION_TEST_BEGIN(); | ||
FUNCTION_TEST_PARAM(INT, error); | ||
FUNCTION_TEST_END(); | ||
|
||
FUNCTION_TEST_RETURN(BOOL, error == ENOTEMPTY || error == EEXIST); | ||
} | ||
|
||
static bool | ||
storagePosixPathRemove(THIS_VOID, const String *path, bool recurse, StorageInterfacePathRemoveParam param) | ||
{ | ||
|
@@ -452,28 +463,39 @@ storagePosixPathRemove(THIS_VOID, const String *path, bool recurse, StorageInter | |
|
||
MEM_CONTEXT_TEMP_BEGIN() | ||
{ | ||
// Recurse if requested | ||
if (recurse) | ||
{ | ||
StoragePosixPathRemoveData data = | ||
{ | ||
.driver = this, | ||
.path = path, | ||
}; | ||
bool removed = false; | ||
|
||
// Remove all sub paths/files | ||
storageInterfaceInfoListP(this, path, storageInfoLevelExists, storagePosixPathRemoveCallback, &data); | ||
} | ||
|
||
// Delete the path | ||
if (rmdir(strZ(path)) == -1) | ||
do | ||
{ | ||
if (errno != ENOENT) // {vm_covered} | ||
THROW_SYS_ERROR_FMT(PathRemoveError, STORAGE_ERROR_PATH_REMOVE, strZ(path)); // {vm_covered} | ||
// If path could not be removed | ||
if (rmdir(strZ(path)) == -1) | ||
{ | ||
// Path does not exist | ||
if (errno == ENOENT) | ||
jreidthompson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
{ | ||
result = false; | ||
removed = true; | ||
} | ||
// Else if not empty but recursion requested then remove all sub paths/files | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a bit confused by the comment and the name of the function. Should the function be named "storagePosixErrorIsNotEmpty"? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It certainly should. Fixed in 5c5f599. |
||
else if (storagePosixErrorIsEmpty(errno) && recurse) // {vm_covered} | ||
{ | ||
StoragePosixPathRemoveData data = | ||
{ | ||
.driver = this, | ||
.path = path, | ||
}; | ||
|
||
// Path does not exist | ||
result = false; | ||
storageInterfaceInfoListP(this, path, storageInfoLevelExists, storagePosixPathRemoveCallback, &data); | ||
} | ||
// Else error | ||
else // {vm_covered} | ||
THROW_SYS_ERROR_FMT(PathRemoveError, STORAGE_ERROR_PATH_REMOVE, strZ(path)); // {vm_covered} | ||
} | ||
// Else path was removed | ||
else | ||
removed = true; | ||
} | ||
while (!removed); | ||
} | ||
MEM_CONTEXT_TEMP_END(); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be a great place to leave a comment 1) keep trying until the directory is fully removed, and 2) why it might not work the first time.
Can we guarantee it can't go into an infinite loop? Perhaps a limit on how many times we retry?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment updated in 8fcb15c and b36d5af.
It seems unlikely, but not impossible. A retry limit would be a good here -- that's pretty standard practice elsewhere. That requires shimming something, but not that big a deal.