Skip to content

Commit c40f530

Browse files
dschoderrickstolee
authored andcommitted
git_config_set_multivar_in_file_gently(): add a lock timeout
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>
1 parent 8c5472f commit c40f530

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

Documentation/config/core.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,3 +734,12 @@ core.abbrev::
734734
If set to "no", no abbreviation is made and the object names
735735
are shown in their full length.
736736
The minimum length is 4.
737+
738+
core.configWriteLockTimeoutMS::
739+
When processes try to write to the config concurrently, it is likely
740+
that one process "wins" and the other process(es) fail to lock the
741+
config file. By configuring a timeout larger than zero, Git can be
742+
told to try to lock the config again a couple times within the
743+
specified timeout. If the timeout is configure to zero (which is the
744+
default), Git will fail immediately when the config is already
745+
locked.

config.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3153,6 +3153,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
31533153
const char *value_pattern,
31543154
unsigned flags)
31553155
{
3156+
static unsigned long timeout_ms = ULONG_MAX;
31563157
int fd = -1, in_fd = -1;
31573158
int ret;
31583159
struct lock_file lock = LOCK_INIT;
@@ -3173,11 +3174,16 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
31733174
if (!config_filename)
31743175
config_filename = filename_buf = git_pathdup("config");
31753176

3177+
if ((long)timeout_ms < 0 &&
3178+
git_config_get_ulong("core.configWriteLockTimeoutMS", &timeout_ms))
3179+
timeout_ms = 0;
3180+
31763181
/*
31773182
* The lock serves a purpose in addition to locking: the new
31783183
* contents of .git/config will be written into it.
31793184
*/
3180-
fd = hold_lock_file_for_update(&lock, config_filename, 0);
3185+
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
3186+
timeout_ms);
31813187
if (fd < 0) {
31823188
error_errno(_("could not lock config file %s"), config_filename);
31833189
ret = CONFIG_NO_LOCK;

0 commit comments

Comments
 (0)