public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 13:35 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 13:35 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:b48f65918a6797ce8024d19412762b742d875405

commit b48f65918a6797ce8024d19412762b742d875405
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 27 05:30:54 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..de99e02af4c 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1295,7 +1297,16 @@ fs::remove_all(const path& p)
       const recursive_directory_iterator end;
       while (dir != end)
 	{
-	  dir.__erase(); // throws on error
+	  /* Avoid exceptions if we may retry on fail on systems that
+	     miss dir entries when removing while iterating.  */
+	  if (count > init_count)
+	    {
+	      dir.__erase(&ec);
+	      if (ec)
+		goto retry;
+	    }
+	  else
+	    dir.__erase(); // throws on error
 	  ++count;
 	}
     }
@@ -1303,7 +1314,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1324,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1344,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1332,7 +1357,12 @@ fs::remove_all(const path& p, error_code& ec)
 	{
 	  dir.__erase(&ec);
 	  if (ec)
-	    return -1;
+	    {
+	      if (count > init_count)
+		goto retry;
+	      else
+		return -1;
+	    }
 	  ++count;
 	}
     }
@@ -1341,7 +1371,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1384,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 15:45 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 15:45 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:537383dad7f2115821ab9a12059a4840089bd855

commit 537383dad7f2115821ab9a12059a4840089bd855
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 27 12:07:19 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..de99e02af4c 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1295,7 +1297,16 @@ fs::remove_all(const path& p)
       const recursive_directory_iterator end;
       while (dir != end)
 	{
-	  dir.__erase(); // throws on error
+	  /* Avoid exceptions if we may retry on fail on systems that
+	     miss dir entries when removing while iterating.  */
+	  if (count > init_count)
+	    {
+	      dir.__erase(&ec);
+	      if (ec)
+		goto retry;
+	    }
+	  else
+	    dir.__erase(); // throws on error
 	  ++count;
 	}
     }
@@ -1303,7 +1314,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1324,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1344,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1332,7 +1357,12 @@ fs::remove_all(const path& p, error_code& ec)
 	{
 	  dir.__erase(&ec);
 	  if (ec)
-	    return -1;
+	    {
+	      if (count > init_count)
+		goto retry;
+	      else
+		return -1;
+	    }
 	  ++count;
 	}
     }
@@ -1341,7 +1371,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1384,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 10:51 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 10:51 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:28bd1631e2cd6c26f2de966e96d54b46fe2dc296

commit 28bd1631e2cd6c26f2de966e96d54b46fe2dc296
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 27 05:30:54 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..de99e02af4c 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1295,7 +1297,16 @@ fs::remove_all(const path& p)
       const recursive_directory_iterator end;
       while (dir != end)
 	{
-	  dir.__erase(); // throws on error
+	  /* Avoid exceptions if we may retry on fail on systems that
+	     miss dir entries when removing while iterating.  */
+	  if (count > init_count)
+	    {
+	      dir.__erase(&ec);
+	      if (ec)
+		goto retry;
+	    }
+	  else
+	    dir.__erase(); // throws on error
 	  ++count;
 	}
     }
@@ -1303,7 +1314,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1324,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1344,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1332,7 +1357,12 @@ fs::remove_all(const path& p, error_code& ec)
 	{
 	  dir.__erase(&ec);
 	  if (ec)
-	    return -1;
+	    {
+	      if (count > init_count)
+		goto retry;
+	      else
+		return -1;
+	    }
 	  ++count;
 	}
     }
@@ -1341,7 +1371,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1384,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27  9:33 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27  9:33 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:10fb66615f12363596b5246d7de05d8993941e60

commit 10fb66615f12363596b5246d7de05d8993941e60
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 27 05:30:54 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 12:44 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 12:44 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:74873e320fab4b7c39f7fc10276a6452da6ce763

commit 74873e320fab4b7c39f7fc10276a6452da6ce763
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 12:30 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 12:30 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:b4199c73cec70cc8d4cac659aa84068b6257ec1c

commit b4199c73cec70cc8d4cac659aa84068b6257ec1c
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 12:22 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 12:22 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:ec9a4b4b3adb65186f6cd1c8b3950f8b49db02b0

commit ec9a4b4b3adb65186f6cd1c8b3950f8b49db02b0
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 10:05 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 10:05 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:6c9d89a9095d5271954d2d4660a3448b29febfd4

commit 6c9d89a9095d5271954d2d4660a3448b29febfd4
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23  7:15 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23  7:15 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:ae6e31b9ce7e733c3e12c1363990490873935577

commit ae6e31b9ce7e733c3e12c1363990490873935577
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-22  5:23 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-22  5:23 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:e4e2717691e13559d3db3e82e25d32d9b95ce5c6

commit e4e2717691e13559d3db3e82e25d32d9b95ce5c6
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-21  0:16 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-21  0:16 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:75ca2e120aa78abf67b51c47db48ac3dc626a136

commit 75ca2e120aa78abf67b51c47db48ac3dc626a136
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-21  0:08 Alexandre Oliva
  0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-21  0:08 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:8aada61fdc69b41c361bd6d533cb25322e0c7cd5

commit 8aada61fdc69b41c361bd6d533cb25322e0c7cd5
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Mon Jun 20 20:19:55 2022 -0300

    libstdc++: retry removal of dir entries if dir removal fails
    
    On some target systems (e.g. rtems6.0), removing directory components
    while iterating over directory entries may cause some of the directory
    entries to be skipped, which prevents the removal of the parent
    directory from succeeding.
    
    Advancing the iterator before removing a member proved not to be
    enough, so I've instead arranged for remove_all to retry the removal
    of components if the removal of the parent dir fails after removing at
    least one entry.  The fail will be permanent only if no components got
    removed in the current try.
    
    
    for  libstdc++-v3/ChangeLog
    
            * src/c++17/fs_ops.cc (remove_all): Retry removal of
            directory entries.
    
    TN: V527-033

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
 {
   error_code ec;
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
     break;
   case ENOENT:
     // Our work here is done.
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
     _GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
   }
 
+  if (count > init_count)
+    {
+      if (int last = fs::remove(p, ec); !ec)
+	return count + last;
+      else
+	// Some systems seem to skip entries in the dir iteration if
+	// you remove dir entries while iterating, so if we removed
+	// anything in the dir in this round, and failed to remove
+	// the dir (presumably because it wasn't empty), retry.
+	goto retry;
+    }
+
   // Remove p itself, which is either a non-directory or is now empty.
   return count + fs::remove(p);
 }
@@ -1321,6 +1335,8 @@ std::uintmax_t
 fs::remove_all(const path& p, error_code& ec)
 {
   uintmax_t count = 0;
+ retry:
+  uintmax_t init_count = count;
   recursive_directory_iterator dir(p, directory_options{64|128}, ec);
   switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
   {
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
   case ENOENT:
     // Our work here is done.
     ec.clear();
-    return 0;
+    return count;
   case ENOTDIR:
   case ELOOP:
     // Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
   // Remove p itself, which is either a non-directory or is now empty.
   if (int last = fs::remove(p, ec); !ec)
     return count + last;
+  if (count > init_count)
+    goto retry;
   return -1;
 }


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-06-27 15:45 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-27 13:35 [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails Alexandre Oliva
  -- strict thread matches above, loose matches on Subject: below --
2022-06-27 15:45 Alexandre Oliva
2022-06-27 10:51 Alexandre Oliva
2022-06-27  9:33 Alexandre Oliva
2022-06-23 12:44 Alexandre Oliva
2022-06-23 12:30 Alexandre Oliva
2022-06-23 12:22 Alexandre Oliva
2022-06-23 10:05 Alexandre Oliva
2022-06-23  7:15 Alexandre Oliva
2022-06-22  5:23 Alexandre Oliva
2022-06-21  0:16 Alexandre Oliva
2022-06-21  0:08 Alexandre Oliva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).