shallow: verify shallow file after taking lock

Before writing the shallow file, we stat() the existing file to make sure it has not been updated since our operation began. However, we do not do so under a lock, so there is a possible race: 1. Process A takes the lock. 2. Process B calls check_shallow_file_for_update and finds no update. 3. Process A commits the lockfile. 4. Process B takes the lock, then overwrite's process A's changes. We can fix this by doing our check while we hold the lock. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Mar 14, 2014 at 23:47 UTC 7839632167bc6ceef20f28bd046f7001493b070f
1 file changed +2 -2
shallow.c
+2 -2
@@ -263,9 +263,9 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,
263 struct strbuf sb = STRBUF_INIT;
264 int fd;
265
266 - check_shallow_file_for_update();
266 fd = hold_lock_file_for_update(shallow_lock, git_path("shallow"),
267 LOCK_DIE_ON_ERROR);
268 + check_shallow_file_for_update();
269 if (write_shallow_commits(&sb, 0, extra)) {
270 if (write_in_full(fd, sb.buf, sb.len) != sb.len)
271 die_errno("failed to write to %s",
@@ -310,9 +310,9 @@ void prune_shallow(int show_only)
310 strbuf_release(&sb);
311 return;
312 }
313 - check_shallow_file_for_update();
313 fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"),
314 LOCK_DIE_ON_ERROR);
315 + check_shallow_file_for_update();
316 if (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {
317 if (write_in_full(fd, sb.buf, sb.len) != sb.len)
318 die_errno("failed to write to %s",