ref_lock: stop leaking lock_files

Since the tempfile code recently relaxed the rule that tempfile structs (and thus locks) need to hang around forever, we no longer have to leak our lock_file structs. In fact, we don't even need to heap-allocate them anymore, since their lifetime can just match that of the surrounding ref_lock (and if we forget to delete a lock, the effect is the same as before: it will eventually go away at program exit). Note that there is a check in unlock_ref() to only rollback a lock file if it has been allocated. We don't need that check anymore; we zero the ref_lock (and thus the lock_file), so at worst we pass a NULL pointer to delete_tempfile(), which considers that a noop. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Sep 5, 2017 at 08:15 UTC ee4d8e455c0981269213eccfd788a9bb9adf77d9
1 file changed +16 -23
refs/files-backend.c
+16 -23
@@ -12,7 +12,7 @@
12
13 struct ref_lock {
14 char *ref_name;
15 - struct lock_file *lk;
15 + struct lock_file lk;
16 struct object_id old_oid;
17 };
18
@@ -418,9 +418,7 @@ out:
418
419 static void unlock_ref(struct ref_lock *lock)
420 {
421 - /* Do not free lock->lk -- atexit() still looks at them */
422 - if (lock->lk)
423 - rollback_lock_file(lock->lk);
421 + rollback_lock_file(&lock->lk);
422 free(lock->ref_name);
423 free(lock);
424 }
@@ -534,11 +532,8 @@ retry:
532 goto error_return;
533 }
534
537 - if (!lock->lk)
538 - lock->lk = xcalloc(1, sizeof(struct lock_file));
539 -
535 if (hold_lock_file_for_update_timeout(
541 - lock->lk, ref_file.buf, LOCK_NO_DEREF,
536 + &lock->lk, ref_file.buf, LOCK_NO_DEREF,
537 get_files_ref_lock_timeout_ms()) < 0) {
538 if (errno == ENOENT && --attempts_remaining > 0) {
539 /*
@@ -949,11 +944,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
944 goto error_return;
945 }
946
952 - lock->lk = xcalloc(1, sizeof(struct lock_file));
953 -
947 lock->ref_name = xstrdup(refname);
948
956 - if (raceproof_create_file(ref_file.buf, create_reflock, lock->lk)) {
949 + if (raceproof_create_file(ref_file.buf, create_reflock, &lock->lk)) {
950 last_errno = errno;
951 unable_to_lock_message(ref_file.buf, errno, err);
952 goto error_return;
@@ -1404,14 +1397,14 @@ static int files_rename_ref(struct ref_store *ref_store,
1397
1398 static int close_ref_gently(struct ref_lock *lock)
1399 {
1407 - if (close_lock_file_gently(lock->lk))
1400 + if (close_lock_file_gently(&lock->lk))
1401 return -1;
1402 return 0;
1403 }
1404
1405 static int commit_ref(struct ref_lock *lock)
1406 {
1414 - char *path = get_locked_file_path(lock->lk);
1407 + char *path = get_locked_file_path(&lock->lk);
1408 struct stat st;
1409
1410 if (!lstat(path, &st) && S_ISDIR(st.st_mode)) {
@@ -1435,7 +1428,7 @@ static int commit_ref(struct ref_lock *lock)
1428 free(path);
1429 }
1430
1438 - if (commit_lock_file(lock->lk))
1431 + if (commit_lock_file(&lock->lk))
1432 return -1;
1433 return 0;
1434 }
@@ -1627,12 +1620,12 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
1620 unlock_ref(lock);
1621 return -1;
1622 }
1630 - fd = get_lock_file_fd(lock->lk);
1623 + fd = get_lock_file_fd(&lock->lk);
1624 if (write_in_full(fd, oid_to_hex(oid), GIT_SHA1_HEXSZ) != GIT_SHA1_HEXSZ ||
1625 write_in_full(fd, &term, 1) != 1 ||
1626 close_ref_gently(lock) < 0) {
1627 strbuf_addf(err,
1635 - "couldn't write '%s'", get_lock_file_path(lock->lk));
1628 + "couldn't write '%s'", get_lock_file_path(&lock->lk));
1629 unlock_ref(lock);
1630 return -1;
1631 }
@@ -1709,7 +1702,7 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)
1702 {
1703 int ret = -1;
1704 #ifndef NO_SYMLINK_HEAD
1712 - char *ref_path = get_locked_file_path(lock->lk);
1705 + char *ref_path = get_locked_file_path(&lock->lk);
1706 unlink(ref_path);
1707 ret = symlink(target, ref_path);
1708 free(ref_path);
@@ -1745,14 +1738,14 @@ static int create_symref_locked(struct files_ref_store *refs,
1738 return 0;
1739 }
1740
1748 - if (!fdopen_lock_file(lock->lk, "w"))
1741 + if (!fdopen_lock_file(&lock->lk, "w"))
1742 return error("unable to fdopen %s: %s",
1750 - lock->lk->tempfile->filename.buf, strerror(errno));
1743 + lock->lk.tempfile->filename.buf, strerror(errno));
1744
1745 update_symref_reflog(refs, lock, refname, target, logmsg);
1746
1747 /* no error check; commit_ref will check ferror */
1755 - fprintf(lock->lk->tempfile->fp, "ref: %s\n", target);
1748 + fprintf(lock->lk.tempfile->fp, "ref: %s\n", target);
1749 if (commit_ref(lock) < 0)
1750 return error("unable to write symref for %s: %s", refname,
1751 strerror(errno));
@@ -2853,12 +2846,12 @@ static int files_reflog_expire(struct ref_store *ref_store,
2846 strerror(errno));
2847 rollback_lock_file(&reflog_lock);
2848 } else if (update &&
2856 - (write_in_full(get_lock_file_fd(lock->lk),
2849 + (write_in_full(get_lock_file_fd(&lock->lk),
2850 oid_to_hex(&cb.last_kept_oid), GIT_SHA1_HEXSZ) != GIT_SHA1_HEXSZ ||
2858 - write_str_in_full(get_lock_file_fd(lock->lk), "\n") != 1 ||
2851 + write_str_in_full(get_lock_file_fd(&lock->lk), "\n") != 1 ||
2852 close_ref_gently(lock) < 0)) {
2853 status |= error("couldn't write %s",
2861 - get_lock_file_path(lock->lk));
2854 + get_lock_file_path(&lock->lk));
2855 rollback_lock_file(&reflog_lock);
2856 } else if (commit_lock_file(&reflog_lock)) {
2857 status |= error("unable to write reflog '%s' (%s)",