{"thread":{"id":"36169","subject":"[PATCH] shallow: verify shallow file after taking lock","startedAt":"2014-03-15T03:47:06Z","lastAt":"2014-03-15T03:47:06Z","messageCount":1,"participants":["Jeff King"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"236776","messageId":"20140315034706.GA3931@sigill.intra.peff.net","threadId":"36169","inReplyTo":null,"subject":"[PATCH] shallow: verify shallow file after taking lock","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2014-03-15T03:47:06Z","receivedAt":"2014-03-15T03:47:06Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"Before writing the shallow file, we stat() the existing file\nto make sure it has not been updated since our operation\nbegan. However, we do not do so under a lock, so there is a\npossible race:\n\n  1. Process A takes the lock.\n\n  2. Process B calls check_shallow_file_for_update and finds\n     no update.\n\n  3. Process A commits the lockfile.\n\n  4. Process B takes the lock, then overwrite's process A's\n     changes.\n\nWe can fix this by doing our check while we hold the lock.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nThis is a repost of:\n\n  http://article.gmane.org/gmane.comp.version-control.git/242795\n\nYou picked up the other two related patches as jk/shallow-update-fix,\nbut I suspect this one just got lost in the noise because I didn't\nformat it as a proper series.\n\n shallow.c | 4 ++--\n 1 file changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/shallow.c b/shallow.c\nindex bbc98b5..75da07a 100644\n--- a/shallow.c\n+++ b/shallow.c\n@@ -246,9 +246,9 @@ void setup_alternate_shallow(struct lock_file *shallow_lock,\n \tstruct strbuf sb = STRBUF_INIT;\n \tint fd;\n \n-\tcheck_shallow_file_for_update();\n \tfd = hold_lock_file_for_update(shallow_lock, git_path(\"shallow\"),\n \t\t\t\t       LOCK_DIE_ON_ERROR);\n+\tcheck_shallow_file_for_update();\n \tif (write_shallow_commits(&sb, 0, extra)) {\n \t\tif (write_in_full(fd, sb.buf, sb.len) != sb.len)\n \t\t\tdie_errno(\"failed to write to %s\",\n@@ -293,9 +293,9 @@ void prune_shallow(int show_only)\n \t\tstrbuf_release(&sb);\n \t\treturn;\n \t}\n-\tcheck_shallow_file_for_update();\n \tfd = hold_lock_file_for_update(&shallow_lock, git_path(\"shallow\"),\n \t\t\t\t       LOCK_DIE_ON_ERROR);\n+\tcheck_shallow_file_for_update();\n \tif (write_shallow_commits_1(&sb, 0, NULL, SEEN_ONLY)) {\n \t\tif (write_in_full(fd, sb.buf, sb.len) != sb.len)\n \t\t\tdie_errno(\"failed to write to %s\",\n-- \n1.9.0.532.g9ab8f58\n"}]}