Skip to content

Conversation

@pcasaretto
Copy link

@pcasaretto pcasaretto commented Nov 27, 2025

CC: Taylor Blau [email protected]
cc: "D. Ben Knoble" [email protected]

@Meme19881401

This comment was marked as spam.

Copy link

@hcmaATshopify hcmaATshopify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would argue for using pid instead of holder everywhere.

Pros of pid

  • Precise: The only payload in the file is the PID. Using “pid” makes it 100% clear and avoids ambiguity.
  • Conventional: Many tools use .pid files or similar conventions, so the meaning is familiar.
  • Unambiguous Code: Variables like pid_file or read_lock_pid() are explicitly about PIDs, not other info.

lockfile.c Outdated
return NULL;

strbuf_addf(&holder_path, "%s%s", lock_path, LOCK_HOLDER_SUFFIX);
fd = open(holder_path.buf, O_WRONLY | O_CREAT | O_TRUNC, mode);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure mode is restrictive enough (match whatever the .lock has and is readable by the creator).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does use the same mode parameter as the lock file:

// In lock_file():
lk->tempfile = create_tempfile_mode(filename.buf, mode);  // lock file
lk->pid_tempfile = create_lock_pid_file(filename.buf, mode);  // PID file - same mode

lockfile.c Outdated

if (lock_holder_info_enabled() &&
!read_lock_holder_pid(lock_path.buf, &holder_pid))
strbuf_addf(buf, _("Lock is held by process %"PRIuMAX".\n\n"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lock (acquired via file '%s') is being held by process .

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given this will print after the "Unable to create '/path/to/.git/index.lock': File exists." message, I think it would be redundant.

lockfile.c Outdated
strbuf_addf(buf, _("Lock is held by process %"PRIuMAX".\n\n"),
holder_pid);

strbuf_addstr(buf, _("Another git process seems to be running in this repository, e.g.\n"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the feature is enabled, we can actually improve this now and be assertive (for instance, if the pid is no longer around, we can say this "lock file is stale and can be removed" or "lock file is valid and held by process "

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turns out kill was already implement and cross platform. Added a liveness check!

return 0;
}

int rollback_lock_file(struct lock_file *lk)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend renaming rollback_lock_file to abort_lock_file for clarity and consistency with Git’s conventions. abort_lock_file is likely the best fit for the Git codebase, as this matches the standard “commit/abort” terminology for transactional semantics.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is not new, I just needed to change it from being an inline function to add new functionality.

strbuf_addf(&holder_path, "%s%s", lock_path, LOCK_HOLDER_SUFFIX);
fd = open(holder_path.buf, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (fd >= 0) {
strbuf_addf(&content, "%"PRIuMAX"\n", (uintmax_t)getpid());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe strbuf_addf(&content, "%ld\n", (long)getpid()); since pid_t is generally int or long; cast to long for portability

Are we sure this will work for non-Unix platforms that might be supported by git? In other words, do we need to ifdef this whole thing so we don't break non-Unix builds?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking around the codebase it seems (uintmax_t)getpid() + PRIuMAX pattern is the established Git convention for portable PID handling:
Examples:

  1. daemon.c:1458 - writes PID to file:

    write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid());
  2. builtin/gc.c:789-790 - writes PID to lockfile:

    strbuf_addf(&sb, "%"PRIuMAX" %s", (uintmax_t) getpid(), my_host);

In terms of cross platform compatibility, I think I got lucky because it was already a first class citizen.
Did a little research and it works across the board.

  • getpid() is available on all Git-supported platforms (provided by libc on Unix, emulated on Windows)
  • pid_t is defined everywhere (native on Unix, typedef int on Windows via mingw-posix.h)

@hcmaATshopify
Copy link

Thanks for doing this @pcasaretto - LGTM!

When a lock file is held, it can be helpful to know which process owns
it, especially when debugging stale locks left behind by crashed
processes. Add an optional feature that creates a companion .lock.pid
file alongside each lock file, containing the PID of the lock holder.

The .lock.pid file is created when a lock is acquired (if enabled), and
automatically cleaned up when the lock is released (via commit or
rollback). The file is registered as a tempfile so it gets cleaned up
by signal and atexit handlers if the process terminates abnormally.

When a lock conflict occurs, the code checks if the PID from the .pid
file is still running using kill(pid, 0). This allows providing
context-aware error messages. With PID info enabled:

  Lock is held by process 12345. Wait for it to finish, or remove
  the lock file to continue.

Or for a stale lock:

  Lock was held by process 12345, which is no longer running.
  Remove the stale lock file to continue.

Without PID info (default):

  Another git process seems to be running in this repository.
  Wait for it to finish, or remove the lock file to continue.

The feature is opt-in via GIT_LOCK_PID_INFO=1 environment variable.

Signed-off-by: Paulo Casaretto <[email protected]>
@pcasaretto pcasaretto marked this pull request as ready for review December 2, 2025 14:14
@pcasaretto
Copy link
Author

/preview

@gitgitgadget
Copy link

gitgitgadget bot commented Dec 2, 2025

Preview email sent as [email protected]

@pcasaretto
Copy link
Author

/submit

@gitgitgadget
Copy link

gitgitgadget bot commented Dec 2, 2025

Submitted as [email protected]

To fetch this version into FETCH_HEAD:

git fetch https://github.com/gitgitgadget/git/ pr-2011/pcasaretto/pid-holder-file-v1

To fetch this version to local tag pr-2011/pcasaretto/pid-holder-file-v1:

git fetch --no-tags https://github.com/gitgitgadget/git/ tag pr-2011/pcasaretto/pid-holder-file-v1

@gitgitgadget
Copy link

gitgitgadget bot commented Dec 2, 2025

On the Git mailing list, "D. Ben Knoble" wrote (reply to this):

On Tue, Dec 2, 2025 at 10:07 AM Paulo Casaretto via GitGitGadget
<[email protected]> wrote:
>
> From: Paulo Casaretto <[email protected]>
>
> When a lock file is held, it can be helpful to know which process owns
> it, especially when debugging stale locks left behind by crashed
> processes. Add an optional feature that creates a companion .lock.pid
> file alongside each lock file, containing the PID of the lock holder.
>
> The .lock.pid file is created when a lock is acquired (if enabled), and
> automatically cleaned up when the lock is released (via commit or
> rollback). The file is registered as a tempfile so it gets cleaned up
> by signal and atexit handlers if the process terminates abnormally.
>
> When a lock conflict occurs, the code checks if the PID from the .pid
> file is still running using kill(pid, 0). This allows providing
> context-aware error messages. With PID info enabled:
>
>   Lock is held by process 12345. Wait for it to finish, or remove
>   the lock file to continue.
>
> Or for a stale lock:
>
>   Lock was held by process 12345, which is no longer running.
>   Remove the stale lock file to continue.
>
> Without PID info (default):
>
>   Another git process seems to be running in this repository.
>   Wait for it to finish, or remove the lock file to continue.
>
> The feature is opt-in via GIT_LOCK_PID_INFO=1 environment variable.
>
> Signed-off-by: Paulo Casaretto <[email protected]>

Sounds interesting. I think by the time I wish I knew what else was
using the lockfile, it's too late for me to alter my environment.
Perhaps (in addition to allowing the environment opt-in) we could
opt-in via configuration? Or is this really only useful, say, on the
server side where the environment is carefully controlled? I don't
relish putting this variable into my environment to take advantage of
something that looks very useful.

Are there downsides that make it necessary to be opt-in? I also
imagine this could be a useful default; occasionally folks at work hit
something similar and ask "what's up with that?"

Only other thing is: just because a process X is running doesn't mean
it was the one holding the lock, right? Since PIDs can be reused.

-- 
D. Ben Knoble

@gitgitgadget
Copy link

gitgitgadget bot commented Dec 2, 2025

User "D. Ben Knoble" <[email protected]> has been added to the cc: list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants