Skip to content

Commit

Permalink
git_config_set_multivar_in_file_gently(): add a lock timeout
Browse files Browse the repository at this point in the history
In particular when multiple processes want to write to the config
simultaneously, it would come in handy to not fail immediately when
another process locked the config, but to gently try again.

This will help with Scalar's functional test suite which wants to
register multiple repositories for maintenance semi-simultaneously.

As not all code paths calling this function read the config (e.g. `git
config`), we have to read the config setting via
`git_config_get_ulong()`.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Sep 16, 2022
1 parent af6589c commit bf45de7
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Documentation/config/core.txt
Original file line number Diff line number Diff line change
Expand Up @@ -749,3 +749,12 @@ core.abbrev::
If set to "no", no abbreviation is made and the object names
are shown in their full length.
The minimum length is 4.

core.configWriteLockTimeoutMS::
When processes try to write to the config concurrently, it is likely
that one process "wins" and the other process(es) fail to lock the
config file. By configuring a timeout larger than zero, Git can be
told to try to lock the config again a couple times within the
specified timeout. If the timeout is configure to zero (which is the
default), Git will fail immediately when the config is already
locked.
8 changes: 7 additions & 1 deletion config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3202,6 +3202,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
const char *value_pattern,
unsigned flags)
{
static unsigned long timeout_ms = ULONG_MAX;
int fd = -1, in_fd = -1;
int ret;
struct lock_file lock = LOCK_INIT;
Expand All @@ -3222,11 +3223,16 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
if (!config_filename)
config_filename = filename_buf = git_pathdup("config");

if ((long)timeout_ms < 0 &&
git_config_get_ulong("core.configWriteLockTimeoutMS", &timeout_ms))
timeout_ms = 0;

/*
* The lock serves a purpose in addition to locking: the new
* contents of .git/config will be written into it.
*/
fd = hold_lock_file_for_update(&lock, config_filename, 0);
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
timeout_ms);
if (fd < 0) {
error_errno(_("could not lock config file %s"), config_filename);
ret = CONFIG_NO_LOCK;
Expand Down

0 comments on commit bf45de7

Please sign in to comment.