Skip to content

Commit ba600d5

Browse files
committed
Merge branch 'pc/lockfile-pid' into seen
Allow recording process ID of the process that holds the lock next to a lockfile for diagnosis. * pc/lockfile-pid: lockfile: add PID file for debugging stale locks
2 parents cae0f20 + 7798604 commit ba600d5

29 files changed

+546
-75
lines changed

Documentation/config/core.adoc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,32 @@ confusion unless you know what you are doing (e.g. you are creating a
348348
read-only snapshot of the same index to a location different from the
349349
repository's usual working tree).
350350

351+
core.lockfilePid::
352+
A comma-separated list of components for which Git should create
353+
a PID file alongside the lock file. When a lock acquisition fails
354+
and a PID file exists, Git can provide additional diagnostic
355+
information about the process holding the lock, including whether
356+
it is still running.
357+
+
358+
This feature is disabled by default. You can enable it for specific
359+
components or use `all` to enable for all components.
360+
+
361+
* `none` disables PID file creation for all components.
362+
* `index` creates PID files for index lock operations.
363+
* `config` creates PID files for config file lock operations.
364+
* `refs` creates PID files for reference lock operations.
365+
* `commit-graph` creates PID files for commit-graph lock operations.
366+
* `midx` creates PID files for multi-pack-index lock operations.
367+
* `shallow` creates PID files for shallow file lock operations.
368+
* `gc` creates PID files for garbage collection lock operations.
369+
* `other` creates PID files for other miscellaneous lock operations.
370+
* `all` enables PID file creation for all components.
371+
+
372+
The PID file is named by inserting `.pid` before the `.lock` suffix.
373+
For example, if the lock file is `index.lock`, the PID file will be
374+
`index.pid.lock`. The file contains `pid <value>` on a single line,
375+
following the same key-value format used by Git object headers.
376+
351377
core.logAllRefUpdates::
352378
Enable the reflog. Updates to a ref <ref> is logged to the file
353379
"`$GIT_DIR/logs/<ref>`", by appending the new and old

apply.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4212,7 +4212,8 @@ static int build_fake_ancestor(struct apply_state *state, struct patch *list)
42124212
}
42134213
}
42144214

4215-
hold_lock_file_for_update(&lock, state->fake_ancestor, LOCK_DIE_ON_ERROR);
4215+
hold_lock_file_for_update(&lock, state->fake_ancestor, LOCK_DIE_ON_ERROR,
4216+
LOCKFILE_PID_OTHER);
42164217
res = write_locked_index(&result, &lock, COMMIT_LOCK);
42174218
discard_index(&result);
42184219

@@ -4869,7 +4870,8 @@ static int apply_patch(struct apply_state *state,
48694870
if (state->index_file)
48704871
hold_lock_file_for_update(&state->lock_file,
48714872
state->index_file,
4872-
LOCK_DIE_ON_ERROR);
4873+
LOCK_DIE_ON_ERROR,
4874+
LOCKFILE_PID_INDEX);
48734875
else
48744876
repo_hold_locked_index(state->repo, &state->lock_file,
48754877
LOCK_DIE_ON_ERROR);

builtin/commit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ static const char *prepare_index(const char **argv, const char *prefix,
540540
path = repo_git_path(the_repository, "next-index-%"PRIuMAX,
541541
(uintmax_t) getpid());
542542
hold_lock_file_for_update(&false_lock, path,
543-
LOCK_DIE_ON_ERROR);
543+
LOCK_DIE_ON_ERROR, LOCKFILE_PID_OTHER);
544544

545545
create_base_index(current_head);
546546
add_remove_files(&partial);

builtin/credential-store.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ static void rewrite_credential_file(const char *fn, struct credential *c,
6868
int timeout_ms = 1000;
6969

7070
repo_config_get_int(the_repository, "credentialstore.locktimeoutms", &timeout_ms);
71-
if (hold_lock_file_for_update_timeout(&credential_lock, fn, 0, timeout_ms) < 0)
71+
if (hold_lock_file_for_update_timeout(&credential_lock, fn, 0, timeout_ms,
72+
LOCKFILE_PID_CONFIG) < 0)
7273
die_errno(_("unable to get credential storage lock in %d ms"), timeout_ms);
7374
if (extra)
7475
print_line(extra);

builtin/difftool.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ static int run_dir_diff(struct repository *repo,
636636
struct lock_file lock = LOCK_INIT;
637637
strbuf_reset(&buf);
638638
strbuf_addf(&buf, "%s/wtindex", tmpdir.buf);
639-
if (hold_lock_file_for_update(&lock, buf.buf, 0) < 0 ||
639+
if (hold_lock_file_for_update(&lock, buf.buf, 0,
640+
LOCKFILE_PID_OTHER) < 0 ||
640641
write_locked_index(&wtindex, &lock, COMMIT_LOCK)) {
641642
ret = error("could not write %s", buf.buf);
642643
goto finish;

builtin/fast-import.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1734,7 +1734,8 @@ static void dump_marks(void)
17341734
return;
17351735
}
17361736

1737-
if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) {
1737+
if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0,
1738+
LOCKFILE_PID_OTHER) < 0) {
17381739
failure |= error_errno(_("unable to write marks file %s"),
17391740
export_marks_file);
17401741
return;

builtin/gc.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid)
749749

750750
pidfile_path = repo_git_path(the_repository, "gc.pid");
751751
fd = hold_lock_file_for_update(&lock, pidfile_path,
752-
LOCK_DIE_ON_ERROR);
752+
LOCK_DIE_ON_ERROR, LOCKFILE_PID_GC);
753753
if (!force) {
754754
static char locking_host[HOST_NAME_MAX + 1];
755755
static char *scan_fmt;
@@ -1017,7 +1017,7 @@ int cmd_gc(int argc,
10171017
if (daemonized) {
10181018
char *path = repo_git_path(the_repository, "gc.log");
10191019
hold_lock_file_for_update(&log_lock, path,
1020-
LOCK_DIE_ON_ERROR);
1020+
LOCK_DIE_ON_ERROR, LOCKFILE_PID_GC);
10211021
dup2(get_lock_file_fd(&log_lock), 2);
10221022
atexit(process_log_file_at_exit);
10231023
free(path);
@@ -1799,7 +1799,8 @@ static int maintenance_run_tasks(struct maintenance_run_opts *opts,
17991799
struct repository *r = the_repository;
18001800
char *lock_path = xstrfmt("%s/maintenance", r->objects->sources->path);
18011801

1802-
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
1802+
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF,
1803+
LOCKFILE_PID_GC) < 0) {
18031804
/*
18041805
* Another maintenance command is running.
18051806
*
@@ -2563,7 +2564,8 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
25632564
lock_file_timeout_ms = 150;
25642565

25652566
fd = hold_lock_file_for_update_timeout(&lk, filename, LOCK_DIE_ON_ERROR,
2566-
lock_file_timeout_ms);
2567+
lock_file_timeout_ms,
2568+
LOCKFILE_PID_GC);
25672569

25682570
/*
25692571
* Does this file already exist? With the intended contents? Is it
@@ -3374,7 +3376,8 @@ static int update_background_schedule(const struct maintenance_start_opts *opts,
33743376
struct lock_file lk;
33753377
char *lock_path = xstrfmt("%s/schedule", the_repository->objects->sources->path);
33763378

3377-
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0) {
3379+
if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF,
3380+
LOCKFILE_PID_GC) < 0) {
33783381
if (errno == EEXIST)
33793382
error(_("unable to create '%s.lock': %s.\n\n"
33803383
"Another scheduled git-maintenance(1) process seems to be running in this\n"

builtin/sparse-checkout.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,8 @@ static int write_patterns_and_update(struct repository *repo,
341341
if (safe_create_leading_directories(repo, sparse_filename))
342342
die(_("failed to create directory for sparse-checkout file"));
343343

344-
hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR);
344+
hold_lock_file_for_update(&lk, sparse_filename, LOCK_DIE_ON_ERROR,
345+
LOCKFILE_PID_OTHER);
345346

346347
result = update_working_directory(repo, pl);
347348
if (result) {

bundle.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ int create_bundle(struct repository *r, const char *path,
520520
bundle_fd = 1;
521521
else
522522
bundle_fd = hold_lock_file_for_update(&lock, path,
523-
LOCK_DIE_ON_ERROR);
523+
LOCK_DIE_ON_ERROR,
524+
LOCKFILE_PID_OTHER);
524525

525526
if (version == -1)
526527
version = min_version;

cache-tree.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,8 @@ int write_index_as_tree(struct object_id *oid, struct index_state *index_state,
736736
struct lock_file lock_file = LOCK_INIT;
737737
int ret;
738738

739-
hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR);
739+
hold_lock_file_for_update(&lock_file, index_path, LOCK_DIE_ON_ERROR,
740+
LOCKFILE_PID_INDEX);
740741

741742
entries = read_index_from(index_state, index_path,
742743
repo_get_git_dir(the_repository));

0 commit comments

Comments
 (0)