Skip to content

Commit f991761

Browse files
peffgitster
authored andcommitted
config: use a static lock_file struct
When modifying git config, we xcalloc() a struct lock_file but never free it. This is necessary because the tempfile code (upon which the locking code is built) requires that the resulting struct remain valid through the life of the program. However, it also confuses leak-checkers like valgrind because only the inner "struct tempfile" is still reachable; no pointer to the outer lock_file is kept. Other code paths solve this by using a single static lock struct. We can do the same here, because we know that we'll only lock and modify one config file at a time (and assertions within the lockfile code will ensure that this remains the case). That removes a real leak (when we fail to free the struct after locking fails) as well as removes the valgrind false positive. It also means that doing N sequential config-writes will use a constant amount of memory, rather than leaving stale lock_files for each. Note that since "lock" is no longer a pointer, it can't be NULL anymore. But that's OK. We used that feature only to avoid calling rollback_lock_file() on an already-committed lock. Since the lockfile code keeps its own "active" flag, it's a noop to rollback an inactive lock, and we don't have to worry about this ourselves. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 3d9c5b5 commit f991761

1 file changed

Lines changed: 7 additions & 17 deletions

File tree

config.c

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2112,7 +2112,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
21122112
{
21132113
int fd = -1, in_fd = -1;
21142114
int ret;
2115-
struct lock_file *lock = NULL;
2115+
static struct lock_file lock;
21162116
char *filename_buf = NULL;
21172117
char *contents = NULL;
21182118
size_t contents_sz;
@@ -2131,8 +2131,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
21312131
* The lock serves a purpose in addition to locking: the new
21322132
* contents of .git/config will be written into it.
21332133
*/
2134-
lock = xcalloc(1, sizeof(struct lock_file));
2135-
fd = hold_lock_file_for_update(lock, config_filename, 0);
2134+
fd = hold_lock_file_for_update(&lock, config_filename, 0);
21362135
if (fd < 0) {
21372136
error_errno("could not lock config file %s", config_filename);
21382137
free(store.key);
@@ -2245,8 +2244,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
22452244
close(in_fd);
22462245
in_fd = -1;
22472246

2248-
if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) {
2249-
error_errno("chmod on %s failed", get_lock_file_path(lock));
2247+
if (chmod(get_lock_file_path(&lock), st.st_mode & 07777) < 0) {
2248+
error_errno("chmod on %s failed", get_lock_file_path(&lock));
22502249
ret = CONFIG_NO_WRITE;
22512250
goto out_free;
22522251
}
@@ -2301,28 +2300,19 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
23012300
contents = NULL;
23022301
}
23032302

2304-
if (commit_lock_file(lock) < 0) {
2303+
if (commit_lock_file(&lock) < 0) {
23052304
error_errno("could not write config file %s", config_filename);
23062305
ret = CONFIG_NO_WRITE;
2307-
lock = NULL;
23082306
goto out_free;
23092307
}
23102308

2311-
/*
2312-
* lock is committed, so don't try to roll it back below.
2313-
* NOTE: Since lockfile.c keeps a linked list of all created
2314-
* lock_file structures, it isn't safe to free(lock). It's
2315-
* better to just leave it hanging around.
2316-
*/
2317-
lock = NULL;
23182309
ret = 0;
23192310

23202311
/* Invalidate the config cache */
23212312
git_config_clear();
23222313

23232314
out_free:
2324-
if (lock)
2325-
rollback_lock_file(lock);
2315+
rollback_lock_file(&lock);
23262316
free(filename_buf);
23272317
if (contents)
23282318
munmap(contents, contents_sz);
@@ -2331,7 +2321,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
23312321
return ret;
23322322

23332323
write_err_out:
2334-
ret = write_error(get_lock_file_path(lock));
2324+
ret = write_error(get_lock_file_path(&lock));
23352325
goto out_free;
23362326

23372327
}

0 commit comments

Comments
 (0)