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

[PATCH v2 2/3] credential-cache--daemon: allow a concurrently created socket dir

From
Farid Zakaria <farid.m.zakaria@gmail.com>
Date
Nov 4, 2026, 19:53 UTC
Message-ID
<20261104-fz-credential-cache-race-v2-2-ddccd0831eba@gmail.com>
In-Reply-To
<20261104-fz-credential-cache-race-v2-0-ddccd0831eba@gmail.com>

When no daemon is running, two "git credential-cache store" run at the same time each try to start one. If the socket directory does not exist yet, both daemons try to create it. The one that comes second dies:

    fatal: unable to mkdir '<home>/.cache/git/credential': File exists
That client then fails with "cache daemon did not start".

Fix this by ignoring EEXIST from mkdir(), and checking the directory's permissions the same way as for one that already existed. We create the directory with mode 0700 instead of fixing it up with chmod() afterwards to avoid a race where another user enters it before the chmod(). A directory created by another daemon was made the same way, so trusting it once its permissions check out is as safe as trusting one that existed before we started.

Signed-off-by: Farid Zakaria <farid.m.zakaria@gmail.com>
---
 builtin/credential-cache--daemon.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/builtin/credential-cache--daemon.c b/builtin/credential-cache--daemon.c
index 5cc39cd172..9e6ed9c922 100644
--- a/builtin/credential-cache--daemon.c
+++ b/builtin/credential-cache--daemon.c
@@ -273,8 +273,18 @@ static void init_socket_directory(const char *path)
 		 */
 		if (safe_create_leading_directories_no_share_const(dir) < 0)
 			die_errno("unable to create directories for '%s'", dir);
-		if (mkdir(dir, 0700) < 0)
-			die_errno("unable to mkdir '%s'", dir);
+		if (mkdir(dir, 0700) < 0) {
+			if (errno != EEXIST)
+				die_errno("unable to mkdir '%s'", dir);
+			/*
+			 * Another daemon created it first; check it like one
+			 * that already existed.
+			 */
+			if (stat(dir, &st))
+				die_errno("unable to stat '%s'", dir);
+			if (st.st_mode & 077)
+				die(_(permissions_advice), dir);
+		}
 	}
 
 	if (chdir(dir))
-- 
2.55.0
Previous: Farid ZakariaNext: Farid Zakaria
Message 13 of 14 in “credential-cache: fix two races when daemons start at once”
  1. 0/2 credential-cache: fix two races when daemons start at onceFarid Zakaria, Nov 1, 2026
  2. 1/2 credential-cache--daemon: allow a concurrently created socket dirFarid Zakaria, Nov 1, 2026
  3. Patrick SteinhardtNov 3, 2026
  4. Farid ZakariaNov 4, 2026
  5. Jeff KingNov 4, 2026
  6. 2/2 credential-cache--daemon: do not take over a running daemon's socketFarid Zakaria, Nov 1, 2026
  7. Patrick SteinhardtNov 3, 2026
  8. Farid ZakariaNov 4, 2026
  9. Junio C HamanoNov 3, 2026
  10. Jeff KingNov 4, 2026
  11. 0/3 credential-cache: fix two races when daemons start at onceFarid Zakaria, Nov 4, 2026
  12. 1/3 credential-cache--daemon: do not apply core.sharedRepositoryFarid Zakaria, Nov 4, 2026
  13. 2/3 credential-cache--daemon: allow a concurrently created socket dirFarid Zakaria, Nov 4, 2026
  14. 3/3 credential-cache--daemon: do not take over a running daemon's socketFarid Zakaria, Nov 4, 2026

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.