diff options
author | Junio C Hamano <gitster@pobox.com> | 2017-09-19 10:47:53 +0900 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2017-09-19 10:47:53 +0900 |
commit | 89563ec379a5b8a74834110588bf042b55315ee2 (patch) | |
tree | ee199aae7d682543aae78e4147a1b19882aacac9 /refs | |
parent | Merge branch 'nd/prune-in-worktree' (diff) | |
parent | stop leaking lock structs in some simple cases (diff) | |
download | tgif-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.c | 50 | ||||
-rw-r--r-- | refs/packed-backend.c | 14 |
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; |