git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v3 1/2] worktree: fix worktree add race.

From
Michal Suchanek <msuchanek@suse.de>
Date
Feb 20, 2019, 16:16 UTC
Message-ID
<e134801d570d0a0c85424eb80b41893f4d8383ca.1550679076.git.msuchanek@suse.de>
In-Reply-To
<cover.1550508544.git.msuchanek@suse.de>

Git runs a stat loop to find a worktree name that's available and then does mkdir on the found name. Turn it to mkdir loop to avoid another invocation of worktree add finding the same free name and creating the directory first.

Signed-off-by: Michal Suchanek <msuchanek@suse.de>
---
v2:
- simplify loop exit condition
- exit early if the mkdir fails for reason other than already present
worktree
- make counter unsigned
---
 builtin/worktree.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 3f9907fcc994..85a604cfe98c 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -268,10 +268,10 @@ static int add_worktree(const char *path, const char *refname,
 	struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
 	struct strbuf sb = STRBUF_INIT;
 	const char *name;
-	struct stat st;
 	struct child_process cp = CHILD_PROCESS_INIT;
 	struct argv_array child_env = ARGV_ARRAY_INIT;
-	int counter = 0, len, ret;
+	unsigned int counter = 0;
+	int len, ret;
 	struct strbuf symref = STRBUF_INIT;
 	struct commit *commit = NULL;
 	int is_branch = 0;
@@ -295,8 +295,12 @@ static int add_worktree(const char *path, const char *refname,
 	if (safe_create_leading_directories_const(sb_repo.buf))
 		die_errno(_("could not create leading directories of '%s'"),
 			  sb_repo.buf);
-	while (!stat(sb_repo.buf, &st)) {
+
+	while (mkdir(sb_repo.buf, 0777)) {
 		counter++;
+		if ((errno != EEXIST) || !counter /* overflow */)
+			die_errno(_("could not create directory of '%s'"),
+				  sb_repo.buf);
 		strbuf_setlen(&sb_repo, len);
 		strbuf_addf(&sb_repo, "%d", counter);
 	}
@@ -306,8 +310,6 @@ static int add_worktree(const char *path, const char *refname,
 	atexit(remove_junk);
 	sigchain_push_common(remove_junk_on_signal);
 
-	if (mkdir(sb_repo.buf, 0777))
-		die_errno(_("could not create directory of '%s'"), sb_repo.buf);
 	junk_git_dir = xstrdup(sb_repo.buf);
 	is_junk = 1;
 
-- 
2.20.1
Previous: Duy NguyenNext: Eric Sunshine
Message 15 of 27 in “worktree add race fix”
  1. 0/2 worktree add race fixMichal Suchanek, Feb 18, 2019
  2. 1/2 worktree: fix worktree add race.Michal Suchanek, Feb 18, 2019
  3. 2/2 setup: don't fail if commondir reference is deleted.Michal Suchanek, Feb 18, 2019
  4. Eric SunshineFeb 18, 2019
  5. Duy NguyenFeb 21, 2019
  6. Michal SuchánekFeb 21, 2019
  7. Phillip WoodFeb 21, 2019
  8. Eric SunshineFeb 21, 2019
  9. Phillip WoodFeb 21, 2019
  10. Michal SuchánekMar 4, 2019
  11. Michal SuchánekFeb 21, 2019
  12. Duy NguyenFeb 22, 2019
  13. Phillip WoodFeb 22, 2019
  14. Duy NguyenFeb 22, 2019
  15. 1/2 worktree: fix worktree add race.Michal Suchanek, Feb 20, 2019
  16. Eric SunshineFeb 20, 2019
  17. Michal SuchánekFeb 20, 2019
  18. Duy NguyenMar 8, 2019
  19. Eric SunshineMar 8, 2019
  20. Junio C HamanoMar 11, 2019
  21. 2/2 setup: don't fail if commondir reference is deleted.Michal Suchanek, Feb 20, 2019
  22. Eric SunshineFeb 20, 2019
  23. Michal SuchánekFeb 20, 2019
  24. Eric SunshineFeb 20, 2019
  25. Eric SunshineFeb 21, 2019
  26. Michal SuchánekFeb 21, 2019
  27. Michal SuchánekFeb 21, 2019

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.