create_symref: write reflog while holding lock
authorJeff King <peff@peff.net>
Tue, 29 Dec 2015 05:57:25 +0000 (00:57 -0500)
committerJunio C Hamano <gitster@pobox.com>
Tue, 29 Dec 2015 18:34:25 +0000 (10:34 -0800)
We generally hold a lock on the matching ref while writing
to its reflog; this prevents two simultaneous writers from
clobbering each other's reflog lines (it does not even have
to be two symref updates; because we don't hold the lock, we
could race with somebody writing to the pointed-to ref via
HEAD, for example).

We can fix this by writing the reflog before we commit the
lockfile. This runs the risk of writing the reflog but
failing the final rename(), but at least we now err on the
same side as the rest of the ref code.

Noticed-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Jeff King <peff@peff.net>
Reviewed-by: Michael Haggerty <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
refs/files-backend.c
index 3d1994debd4214b8e3a257576d7f8b09dbdb06f2..180c837d11f75249049e9732905c05d67e7b583f 100644 (file)
@@ -2850,12 +2850,13 @@ static int create_symref_locked(struct ref_lock *lock, const char *refname,
                return error("unable to fdopen %s: %s",
                             lock->lk->tempfile.filename.buf, strerror(errno));
 
+       update_symref_reflog(lock, refname, target, logmsg);
+
        /* no error check; commit_ref will check ferror */
        fprintf(lock->lk->tempfile.fp, "ref: %s\n", target);
        if (commit_ref(lock) < 0)
                return error("unable to write symref for %s: %s", refname,
                             strerror(errno));
-       update_symref_reflog(lock, refname, target, logmsg);
        return 0;
 }