Skip to content

Commit 384cf4d

Browse files
dschomjcheetham
authored andcommitted
Merge branch 'scalar-gentler-config-locking'
Allow concurrent `scalar register` and `scalar unregister` calls to be more collaborative when trying to lock the global Git config at the very same time. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents e2edaba + 4c721a0 commit 384cf4d

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

Documentation/config/core.adoc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,3 +771,12 @@ core.WSLCompat::
771771
The default value is false. When set to true, Git will set the mode
772772
bits of the file in the way of wsl, so that the executable flag of
773773
files can be set or read correctly.
774+
775+
core.configWriteLockTimeoutMS::
776+
When processes try to write to the config concurrently, it is likely
777+
that one process "wins" and the other process(es) fail to lock the
778+
config file. By configuring a timeout larger than zero, Git can be
779+
told to try to lock the config again a couple times within the
780+
specified timeout. If the timeout is configure to zero (which is the
781+
default), Git will fail immediately when the config is already
782+
locked.

config.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3178,6 +3178,7 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
31783178
const char *comment,
31793179
unsigned flags)
31803180
{
3181+
static unsigned long timeout_ms = ULONG_MAX;
31813182
int fd = -1, in_fd = -1;
31823183
int ret;
31833184
struct lock_file lock = LOCK_INIT;
@@ -3198,11 +3199,16 @@ int repo_config_set_multivar_in_file_gently(struct repository *r,
31983199
if (!config_filename)
31993200
config_filename = filename_buf = repo_git_path(r, "config");
32003201

3202+
if ((long)timeout_ms < 0 &&
3203+
git_config_get_ulong("core.configWriteLockTimeoutMS", &timeout_ms))
3204+
timeout_ms = 0;
3205+
32013206
/*
32023207
* The lock serves a purpose in addition to locking: the new
32033208
* contents of .git/config will be written into it.
32043209
*/
3205-
fd = hold_lock_file_for_update(&lock, config_filename, 0);
3210+
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
3211+
timeout_ms);
32063212
if (fd < 0) {
32073213
error_errno(_("could not lock config file %s"), config_filename);
32083214
ret = CONFIG_NO_LOCK;

scalar.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ static int set_recommended_config(int reconfigure)
171171
{ "core.safeCRLF", "false" },
172172
{ "fetch.showForcedUpdates", "false" },
173173
{ "pack.usePathWalk", "true" },
174+
{ "core.configWriteLockTimeoutMS", "150" },
174175
{ NULL, NULL },
175176
};
176177
int i;
@@ -212,6 +213,11 @@ static int set_recommended_config(int reconfigure)
212213

213214
static int toggle_maintenance(int enable)
214215
{
216+
unsigned long ul;
217+
218+
if (git_config_get_ulong("core.configWriteLockTimeoutMS", &ul))
219+
git_config_push_parameter("core.configWriteLockTimeoutMS=150");
220+
215221
return run_git("maintenance",
216222
enable ? "start" : "unregister",
217223
enable ? NULL : "--force",
@@ -221,10 +227,14 @@ static int toggle_maintenance(int enable)
221227
static int add_or_remove_enlistment(int add)
222228
{
223229
int res;
230+
unsigned long ul;
224231

225232
if (!the_repository->worktree)
226233
die(_("Scalar enlistments require a worktree"));
227234

235+
if (git_config_get_ulong("core.configWriteLockTimeoutMS", &ul))
236+
git_config_push_parameter("core.configWriteLockTimeoutMS=150");
237+
228238
res = run_git("config", "--global", "--get", "--fixed-value",
229239
"scalar.repo", the_repository->worktree, NULL);
230240

0 commit comments

Comments
 (0)