Thread (15 messages) flat view 15 messages, 3 authors, 2016-06-15
STALE3743d

[PATCH 4/5] safe_create_leading_directories(): fix a mkdir/rmdir race

From: Michael Haggerty <hidden>
Date: 2016-06-15 22:59:30
Subsystem: the rest · Maintainer: Linus Torvalds

It could be that some other process is trying to clean up empty
directories at the same time that safe_create_leading_directories() is
attempting to create them.  In this case, it could happen that
directory "a/b" was present at the end of one iteration of the loop
(either it was already present or we just created it ourselves), but
by the time we try to create directory "a/b/c", directory "a/b" has
been deleted.  In fact, directory "a" might also have been deleted.

So, if a call to mkdir() fails with ENOENT, then try checking/making
all directories again from the beginning.  Attempt up to three times
before giving up.

Signed-off-by: Michael Haggerty <redacted>
---
 sha1_file.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
diff --git a/sha1_file.c b/sha1_file.c
index dcfd35a..abcb56b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -108,6 +108,7 @@ int mkdir_in_gitdir(const char *path)
 int safe_create_leading_directories(char *path)
 {
 	char *next_component = path + offset_1st_component(path);
+	int attempts = 3;
 	int retval = 0;
 
 	while (!retval && next_component) {
@@ -132,6 +133,16 @@ int safe_create_leading_directories(char *path)
 			if (errno == EEXIST &&
 			    !stat(path, &st) && S_ISDIR(st.st_mode)) {
 				; /* somebody created it since we checked */
+			} else if (errno == ENOENT && --attempts) {
+				/*
+				 * Either mkdir() failed bacause
+				 * somebody just pruned the containing
+				 * directory, or stat() failed because
+				 * the file that was in our way was
+				 * just removed.  Either way, try
+				 * again from the beginning:
+				 */
+				next_component = path + offset_1st_component(path);
 			} else {
 				retval = -1;
 			}
-- 
1.8.5.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help