summaryrefslogtreecommitdiff
path: root/refs
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <gitster@pobox.com>2017-09-19 10:47:53 +0900
committerLibravatar Junio C Hamano <gitster@pobox.com>2017-09-19 10:47:53 +0900
commit89563ec379a5b8a74834110588bf042b55315ee2 (patch)
treeee199aae7d682543aae78e4147a1b19882aacac9 /refs
parentMerge branch 'nd/prune-in-worktree' (diff)
parentstop leaking lock structs in some simple cases (diff)
downloadtgif-89563ec379a5b8a74834110588bf042b55315ee2.tar.xz
Merge branch 'jk/incore-lockfile-removal'
The long-standing rule that an in-core lockfile instance, once it is used, must not be freed, has been lifted and the lockfile and tempfile APIs have been updated to reduce the chance of programming errors. * jk/incore-lockfile-removal: stop leaking lock structs in some simple cases ref_lock: stop leaking lock_files lockfile: update lifetime requirements in documentation tempfile: auto-allocate tempfiles on heap tempfile: remove deactivated list entries tempfile: use list.h for linked list tempfile: release deactivated strbufs instead of resetting tempfile: robustify cleanup handler tempfile: factor out deactivation tempfile: factor out activation tempfile: replace die("BUG") with BUG() tempfile: handle NULL tempfile pointers gracefully tempfile: prefer is_tempfile_active to bare access lockfile: do not rollback lock on failed close tempfile: do not delete tempfile on failed close always check return value of close_tempfile verify_signed_buffer: prefer close_tempfile() to close() setup_temporary_shallow: move tempfile struct into function setup_temporary_shallow: avoid using inactive tempfile write_index_as_tree: cleanup tempfile on error
Diffstat (limited to 'refs')
-rw-r--r--refs/files-backend.c50
-rw-r--r--refs/packed-backend.c14
2 files changed, 30 insertions, 34 deletions
diff --git a/refs/files-backend.c b/refs/files-backend.c
index cda790dcbc..a7cc65d0de 100644
--- a/refs/files-backend.c
+++ b/refs/files-backend.c
@@ -12,7 +12,7 @@
struct ref_lock {
char *ref_name;
- struct lock_file *lk;
+ struct lock_file lk;
struct object_id old_oid;
};
@@ -409,9 +409,7 @@ out:
static void unlock_ref(struct ref_lock *lock)
{
- /* Do not free lock->lk -- atexit() still looks at them */
- if (lock->lk)
- rollback_lock_file(lock->lk);
+ rollback_lock_file(&lock->lk);
free(lock->ref_name);
free(lock);
}
@@ -525,11 +523,8 @@ retry:
goto error_return;
}
- if (!lock->lk)
- lock->lk = xcalloc(1, sizeof(struct lock_file));
-
if (hold_lock_file_for_update_timeout(
- lock->lk, ref_file.buf, LOCK_NO_DEREF,
+ &lock->lk, ref_file.buf, LOCK_NO_DEREF,
get_files_ref_lock_timeout_ms()) < 0) {
if (errno == ENOENT && --attempts_remaining > 0) {
/*
@@ -940,11 +935,9 @@ static struct ref_lock *lock_ref_sha1_basic(struct files_ref_store *refs,
goto error_return;
}
- lock->lk = xcalloc(1, sizeof(struct lock_file));
-
lock->ref_name = xstrdup(refname);
- if (raceproof_create_file(ref_file.buf, create_reflock, lock->lk)) {
+ if (raceproof_create_file(ref_file.buf, create_reflock, &lock->lk)) {
last_errno = errno;
unable_to_lock_message(ref_file.buf, errno, err);
goto error_return;
@@ -1393,16 +1386,16 @@ static int files_rename_ref(struct ref_store *ref_store,
return ret;
}
-static int close_ref(struct ref_lock *lock)
+static int close_ref_gently(struct ref_lock *lock)
{
- if (close_lock_file(lock->lk))
+ if (close_lock_file_gently(&lock->lk))
return -1;
return 0;
}
static int commit_ref(struct ref_lock *lock)
{
- char *path = get_locked_file_path(lock->lk);
+ char *path = get_locked_file_path(&lock->lk);
struct stat st;
if (!lstat(path, &st) && S_ISDIR(st.st_mode)) {
@@ -1426,7 +1419,7 @@ static int commit_ref(struct ref_lock *lock)
free(path);
}
- if (commit_lock_file(lock->lk))
+ if (commit_lock_file(&lock->lk))
return -1;
return 0;
}
@@ -1618,12 +1611,12 @@ static int write_ref_to_lockfile(struct ref_lock *lock,
unlock_ref(lock);
return -1;
}
- fd = get_lock_file_fd(lock->lk);
+ fd = get_lock_file_fd(&lock->lk);
if (write_in_full(fd, oid_to_hex(oid), GIT_SHA1_HEXSZ) != GIT_SHA1_HEXSZ ||
write_in_full(fd, &term, 1) != 1 ||
- close_ref(lock) < 0) {
+ close_ref_gently(lock) < 0) {
strbuf_addf(err,
- "couldn't write '%s'", get_lock_file_path(lock->lk));
+ "couldn't write '%s'", get_lock_file_path(&lock->lk));
unlock_ref(lock);
return -1;
}
@@ -1700,7 +1693,7 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)
{
int ret = -1;
#ifndef NO_SYMLINK_HEAD
- char *ref_path = get_locked_file_path(lock->lk);
+ char *ref_path = get_locked_file_path(&lock->lk);
unlink(ref_path);
ret = symlink(target, ref_path);
free(ref_path);
@@ -1736,14 +1729,14 @@ static int create_symref_locked(struct files_ref_store *refs,
return 0;
}
- if (!fdopen_lock_file(lock->lk, "w"))
+ if (!fdopen_lock_file(&lock->lk, "w"))
return error("unable to fdopen %s: %s",
- lock->lk->tempfile.filename.buf, strerror(errno));
+ lock->lk.tempfile->filename.buf, strerror(errno));
update_symref_reflog(refs, lock, refname, target, logmsg);
/* no error check; commit_ref will check ferror */
- fprintf(lock->lk->tempfile.fp, "ref: %s\n", target);
+ 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));
@@ -2425,7 +2418,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
* the lockfile is still open. Close it to
* free up the file descriptor:
*/
- if (close_ref(lock)) {
+ if (close_ref_gently(lock)) {
strbuf_addf(err, "couldn't close '%s.lock'",
update->refname);
ret = TRANSACTION_GENERIC_ERROR;
@@ -2905,16 +2898,17 @@ static int files_reflog_expire(struct ref_store *ref_store,
!(type & REF_ISSYMREF) &&
!is_null_oid(&cb.last_kept_oid);
- if (close_lock_file(&reflog_lock)) {
+ if (close_lock_file_gently(&reflog_lock)) {
status |= error("couldn't write %s: %s", log_file,
strerror(errno));
+ rollback_lock_file(&reflog_lock);
} else if (update &&
- (write_in_full(get_lock_file_fd(lock->lk),
+ (write_in_full(get_lock_file_fd(&lock->lk),
oid_to_hex(&cb.last_kept_oid), GIT_SHA1_HEXSZ) != GIT_SHA1_HEXSZ ||
- write_str_in_full(get_lock_file_fd(lock->lk), "\n") != 1 ||
- close_ref(lock) < 0)) {
+ write_str_in_full(get_lock_file_fd(&lock->lk), "\n") != 1 ||
+ close_ref_gently(lock) < 0)) {
status |= error("couldn't write %s",
- get_lock_file_path(lock->lk));
+ get_lock_file_path(&lock->lk));
rollback_lock_file(&reflog_lock);
} else if (commit_lock_file(&reflog_lock)) {
status |= error("unable to write reflog '%s' (%s)",
diff --git a/refs/packed-backend.c b/refs/packed-backend.c
index 412c85034f..321608a114 100644
--- a/refs/packed-backend.c
+++ b/refs/packed-backend.c
@@ -75,7 +75,7 @@ struct packed_ref_store {
* "packed-refs" file. Note that this (and thus the enclosing
* `packed_ref_store`) must not be freed.
*/
- struct tempfile tempfile;
+ struct tempfile *tempfile;
};
struct ref_store *packed_ref_store_create(const char *path,
@@ -545,8 +545,9 @@ int packed_refs_lock(struct ref_store *ref_store, int flags, struct strbuf *err)
return -1;
}
- if (close_lock_file(&refs->lock)) {
+ if (close_lock_file_gently(&refs->lock)) {
strbuf_addf(err, "unable to close %s: %s", refs->path, strerror(errno));
+ rollback_lock_file(&refs->lock);
return -1;
}
@@ -627,7 +628,8 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
*/
packed_refs_path = get_locked_file_path(&refs->lock);
strbuf_addf(&sb, "%s.new", packed_refs_path);
- if (create_tempfile(&refs->tempfile, sb.buf) < 0) {
+ refs->tempfile = create_tempfile(sb.buf);
+ if (!refs->tempfile) {
strbuf_addf(err, "unable to create file %s: %s",
sb.buf, strerror(errno));
strbuf_release(&sb);
@@ -635,7 +637,7 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
}
strbuf_release(&sb);
- out = fdopen_tempfile(&refs->tempfile, "w");
+ out = fdopen_tempfile(refs->tempfile, "w");
if (!out) {
strbuf_addf(err, "unable to fdopen packed-refs tempfile: %s",
strerror(errno));
@@ -644,7 +646,7 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
if (fprintf(out, "%s", PACKED_REFS_HEADER) < 0) {
strbuf_addf(err, "error writing to %s: %s",
- get_tempfile_path(&refs->tempfile), strerror(errno));
+ get_tempfile_path(refs->tempfile), strerror(errno));
goto error;
}
@@ -656,7 +658,7 @@ int commit_packed_refs(struct ref_store *ref_store, struct strbuf *err)
if (write_packed_entry(out, iter->refname, iter->oid->hash,
peel_error ? NULL : peeled.hash)) {
strbuf_addf(err, "error writing to %s: %s",
- get_tempfile_path(&refs->tempfile),
+ get_tempfile_path(refs->tempfile),
strerror(errno));
ref_iterator_abort(iter);
goto error;