From: Brandon Williams <bmwill@google.com>
To: Jeff King <peff@peff.net>
Cc: "Lars Schneider" <larsxschneider@gmail.com>,
"Martin Ågren" <martin.agren@gmail.com>,
"Git Users" <git@vger.kernel.org>
Subject: Re: [PATCH] config: use a static lock_file struct
Date: Tue, 29 Aug 2017 12:09:28 -0700 [thread overview]
Message-ID: <20170829190928.GD131745@google.com> (raw)
In-Reply-To: <20170829185850.tfmjoa5u5sfuwpgi@sigill.intra.peff.net>
On 08/29, Jeff King wrote:
> On Tue, Aug 29, 2017 at 02:53:41PM -0400, Jeff King wrote:
>
> > It looks like the config code has a minor-ish leak. Patch to follow.
>
> Here it is.
>
> -- >8 --
> Subject: [PATCH] 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.
Is this just due to a limitation in the tempfile code? Would it be
possible to improve the tempfile code such that we don't need to require
that a tempfile, once created, is required to exist for the remaining
life of the program?
>
> 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>
> ---
> In the long run we may want to drop the "tempfiles must remain forever"
> rule. This is certainly not the first time it has caused confusion or
> leaks. And I don't think it's a fundamental issue, just the way the code
> is written. But in the interim, this fix is probably worth doing.
>
> config.c | 24 +++++++-----------------
> 1 file changed, 7 insertions(+), 17 deletions(-)
>
> diff --git a/config.c b/config.c
> index d0d8ce823a..1603f96e40 100644
> --- a/config.c
> +++ b/config.c
> @@ -2450,7 +2450,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
> {
> int fd = -1, in_fd = -1;
> int ret;
> - struct lock_file *lock = NULL;
> + static struct lock_file lock;
> char *filename_buf = NULL;
> char *contents = NULL;
> size_t contents_sz;
> @@ -2469,8 +2469,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
> * The lock serves a purpose in addition to locking: the new
> * contents of .git/config will be written into it.
> */
> - lock = xcalloc(1, sizeof(struct lock_file));
> - fd = hold_lock_file_for_update(lock, config_filename, 0);
> + fd = hold_lock_file_for_update(&lock, config_filename, 0);
> if (fd < 0) {
> error_errno("could not lock config file %s", config_filename);
> free(store.key);
> @@ -2583,8 +2582,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
> close(in_fd);
> in_fd = -1;
>
> - if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) {
> - error_errno("chmod on %s failed", get_lock_file_path(lock));
> + if (chmod(get_lock_file_path(&lock), st.st_mode & 07777) < 0) {
> + error_errno("chmod on %s failed", get_lock_file_path(&lock));
> ret = CONFIG_NO_WRITE;
> goto out_free;
> }
> @@ -2639,28 +2638,19 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
> contents = NULL;
> }
>
> - if (commit_lock_file(lock) < 0) {
> + if (commit_lock_file(&lock) < 0) {
> error_errno("could not write config file %s", config_filename);
> ret = CONFIG_NO_WRITE;
> - lock = NULL;
> goto out_free;
> }
>
> - /*
> - * lock is committed, so don't try to roll it back below.
> - * NOTE: Since lockfile.c keeps a linked list of all created
> - * lock_file structures, it isn't safe to free(lock). It's
> - * better to just leave it hanging around.
> - */
> - lock = NULL;
> ret = 0;
>
> /* Invalidate the config cache */
> git_config_clear();
>
> out_free:
> - if (lock)
> - rollback_lock_file(lock);
> + rollback_lock_file(&lock);
> free(filename_buf);
> if (contents)
> munmap(contents, contents_sz);
> @@ -2669,7 +2659,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
> return ret;
>
> write_err_out:
> - ret = write_error(get_lock_file_path(lock));
> + ret = write_error(get_lock_file_path(&lock));
> goto out_free;
>
> }
> --
> 2.14.1.721.gc5bc1565f1
>
--
Brandon Williams
next prev parent reply other threads:[~2017-08-29 19:09 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-08-27 7:37 [PATCH] pkt-line: re-'static'-ify buffer in packet_write_fmt_1() Martin Ågren
2017-08-27 15:41 ` Jeff King
2017-08-27 18:25 ` Jeff King
2017-08-27 18:21 ` Lars Schneider
2017-08-27 19:09 ` Martin Ågren
2017-08-27 19:15 ` Jeff King
2017-08-27 20:04 ` Lars Schneider
2017-08-27 23:23 ` Jeff King
2017-08-28 4:11 ` Martin Ågren
2017-08-28 17:52 ` Stefan Beller
2017-08-28 17:58 ` Jeff King
2017-09-05 10:03 ` Junio C Hamano
2017-08-29 17:51 ` Lars Schneider
2017-08-29 18:53 ` Jeff King
2017-08-29 18:58 ` [PATCH] config: use a static lock_file struct Jeff King
2017-08-29 19:09 ` Brandon Williams [this message]
2017-08-29 19:10 ` Brandon Williams
2017-08-29 19:12 ` Jeff King
2017-08-30 3:25 ` Michael Haggerty
2017-08-30 4:31 ` Jeff King
2017-08-30 4:55 ` Michael Haggerty
2017-08-30 4:55 ` Jeff King
2017-08-30 5:55 ` Jeff King
2017-08-30 7:07 ` Michael Haggerty
2017-09-02 8:44 ` Jeff King
2017-09-02 13:50 ` Jeff King
2017-08-30 6:55 ` Michael Haggerty
2017-08-30 19:53 ` Jeff King
2017-08-30 19:57 ` Brandon Williams
2017-08-30 20:11 ` Jeff King
2017-08-30 21:06 ` Brandon Williams
2017-08-31 4:09 ` Jeff King
2017-09-06 3:59 ` Junio C Hamano
2017-09-06 12:41 ` Jeff King
2017-08-29 19:22 ` [PATCH] pkt-line: re-'static'-ify buffer in packet_write_fmt_1() Martin Ågren
2017-08-29 21:48 ` Jeff King
2017-08-30 5:31 ` Jeff King
2017-09-05 10:03 ` Junio C Hamano
2017-10-10 4:06 ` [PATCH 0/2] Do not call cmd_*() as a subroutine Junio C Hamano
2017-10-10 4:06 ` [PATCH 1/2] describe: do not use " Junio C Hamano
2017-10-10 13:43 ` SZEDER Gábor
2017-10-11 6:00 ` Junio C Hamano
2017-10-10 4:06 ` [PATCH 2/2] merge-ours: " Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170829190928.GD131745@google.com \
--to=bmwill@google.com \
--cc=git@vger.kernel.org \
--cc=larsxschneider@gmail.com \
--cc=martin.agren@gmail.com \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.