public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Alexandre Oliva <aoliva@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
Date: Tue, 21 Jun 2022 00:08:56 +0000 (GMT)	[thread overview]
Message-ID: <20220621000856.A798B38418A8@sourceware.org> (raw)

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;
 }


             reply	other threads:[~2022-06-21  0:08 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-21  0:08 Alexandre Oliva [this message]
2022-06-21  0:16 Alexandre Oliva
2022-06-22  5:23 Alexandre Oliva
2022-06-23  7:15 Alexandre Oliva
2022-06-23 10:05 Alexandre Oliva
2022-06-23 12:22 Alexandre Oliva
2022-06-23 12:30 Alexandre Oliva
2022-06-23 12:44 Alexandre Oliva
2022-06-27  9:33 Alexandre Oliva
2022-06-27 10:51 Alexandre Oliva
2022-06-27 13:35 Alexandre Oliva
2022-06-27 15:45 Alexandre Oliva

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220621000856.A798B38418A8@sourceware.org \
    --to=aoliva@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    --cc=libstdc++-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).