Coverage Report

Created: 2026-10-17 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/git/lockfile.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2005, Junio C Hamano
3
 */
4
5
#define USE_THE_REPOSITORY_VARIABLE
6
7
#include "git-compat-util.h"
8
#include "abspath.h"
9
#include "gettext.h"
10
#include "lockfile.h"
11
#include "parse.h"
12
#include "repository.h"
13
#include "strbuf.h"
14
#include "wrapper.h"
15
16
/*
17
 * path = absolute or relative path name
18
 *
19
 * Remove the last path name element from path (leaving the preceding
20
 * "/", if any).  If path is empty or the root directory ("/"), set
21
 * path to the empty string.
22
 */
23
static void trim_last_path_component(struct strbuf *path)
24
0
{
25
0
  int i = path->len;
26
27
  /* back up past trailing slashes, if any */
28
0
  while (i && is_dir_sep(path->buf[i - 1]))
29
0
    i--;
30
31
  /*
32
   * then go backwards until a slash, or the beginning of the
33
   * string
34
   */
35
0
  while (i && !is_dir_sep(path->buf[i - 1]))
36
0
    i--;
37
38
0
  strbuf_setlen(path, i);
39
0
}
40
41
42
/* We allow "recursive" symbolic links. Only within reason, though */
43
0
#define MAXDEPTH 5
44
45
/*
46
 * path contains a path that might be a symlink.
47
 *
48
 * If path is a symlink, attempt to overwrite it with a path to the
49
 * real file or directory (which may or may not exist), following a
50
 * chain of symlinks if necessary.  Otherwise, leave path unmodified.
51
 *
52
 * This is a best-effort routine.  If an error occurs, path will
53
 * either be left unmodified or will name a different symlink in a
54
 * symlink chain that started with the original path.
55
 */
56
static void resolve_symlink(struct strbuf *path)
57
0
{
58
0
  int depth = MAXDEPTH;
59
0
  static struct strbuf link = STRBUF_INIT;
60
61
0
  while (depth--) {
62
0
    if (strbuf_readlink(&link, path->buf, path->len) < 0)
63
0
      break;
64
65
0
    if (is_absolute_path(link.buf))
66
      /* absolute path simply replaces p */
67
0
      strbuf_reset(path);
68
0
    else
69
      /*
70
       * link is a relative path, so replace the
71
       * last element of p with it.
72
       */
73
0
      trim_last_path_component(path);
74
75
0
    strbuf_addbuf(path, &link);
76
0
  }
77
0
  strbuf_reset(&link);
78
0
}
79
80
/*
81
 * Lock PID file functions - write PID to a foo~pid.lock file alongside
82
 * the lock file for debugging stale locks. The PID file is registered
83
 * as a tempfile so it gets cleaned up by signal/atexit handlers.
84
 *
85
 * Naming: For "foo.lock", the PID file is "foo~pid.lock". The tilde is
86
 * forbidden in refnames and allowed in Windows filenames, guaranteeing
87
 * no collision with the refs namespace.
88
 */
89
90
/* Global config variable, initialized from core.lockfilePid */
91
int lockfile_pid_enabled;
92
93
/*
94
 * Path generation helpers.
95
 * Given base path "foo", generate:
96
 *   - lock path: "foo.lock"
97
 *   - pid path:  "foo-pid.lock"
98
 */
99
static void get_lock_path(struct strbuf *out, const char *path)
100
0
{
101
0
  strbuf_addstr(out, path);
102
0
  strbuf_addstr(out, LOCK_SUFFIX);
103
0
}
104
105
static void get_pid_path(struct strbuf *out, const char *path)
106
0
{
107
0
  strbuf_addstr(out, path);
108
0
  strbuf_addstr(out, LOCK_PID_INFIX);
109
0
  strbuf_addstr(out, LOCK_SUFFIX);
110
0
}
111
112
static struct tempfile *create_lock_pid_file(const char *pid_path, int mode)
113
0
{
114
0
  struct strbuf content = STRBUF_INIT;
115
0
  struct tempfile *pid_tempfile = NULL;
116
0
  int fd;
117
118
0
  if (!lockfile_pid_enabled)
119
0
    goto out;
120
121
0
  fd = open(pid_path, O_WRONLY | O_CREAT | O_EXCL, mode);
122
0
  if (fd < 0)
123
0
    goto out;
124
125
0
  strbuf_addf(&content, "pid %" PRIuMAX "\n", (uintmax_t)getpid());
126
0
  if (write_in_full(fd, content.buf, content.len) < 0) {
127
0
    warning_errno(_("could not write lock pid file '%s'"), pid_path);
128
0
    close(fd);
129
0
    unlink(pid_path);
130
0
    goto out;
131
0
  }
132
133
0
  close(fd);
134
0
  pid_tempfile = register_tempfile(pid_path);
135
136
0
out:
137
0
  strbuf_release(&content);
138
0
  return pid_tempfile;
139
0
}
140
141
static int read_lock_pid(const char *pid_path, uintmax_t *pid_out)
142
0
{
143
0
  struct strbuf content = STRBUF_INIT;
144
0
  const char *val;
145
0
  int ret = -1;
146
147
0
  if (strbuf_read_file(&content, pid_path, LOCK_PID_MAXLEN) <= 0)
148
0
    goto out;
149
150
0
  strbuf_rtrim(&content);
151
152
0
  if (skip_prefix(content.buf, "pid ", &val)) {
153
0
    char *endptr;
154
0
    *pid_out = strtoumax(val, &endptr, 10);
155
0
    if (*pid_out > 0 && !*endptr)
156
0
      ret = 0;
157
0
  }
158
159
0
  if (ret)
160
0
    warning(_("malformed lock pid file '%s'"), pid_path);
161
162
0
out:
163
0
  strbuf_release(&content);
164
0
  return ret;
165
0
}
166
167
/* Make sure errno contains a meaningful value on error */
168
static int lock_file(struct repository *r, struct lock_file *lk,
169
         const char *path, int flags, int mode)
170
0
{
171
0
  struct strbuf base_path = STRBUF_INIT;
172
0
  struct strbuf lock_path = STRBUF_INIT;
173
0
  struct strbuf pid_path = STRBUF_INIT;
174
175
0
  strbuf_addstr(&base_path, path);
176
0
  if (!(flags & LOCK_NO_DEREF))
177
0
    resolve_symlink(&base_path);
178
179
0
  get_lock_path(&lock_path, base_path.buf);
180
0
  get_pid_path(&pid_path, base_path.buf);
181
182
0
  lk->tempfile = repo_create_tempfile_mode(r, lock_path.buf, mode);
183
0
  if (lk->tempfile)
184
0
    lk->pid_tempfile = create_lock_pid_file(pid_path.buf, mode);
185
186
0
  strbuf_release(&base_path);
187
0
  strbuf_release(&lock_path);
188
0
  strbuf_release(&pid_path);
189
0
  return lk->tempfile ? lk->tempfile->fd : -1;
190
0
}
191
192
/*
193
 * Constants defining the gaps between attempts to lock a file. The
194
 * first backoff period is approximately INITIAL_BACKOFF_MS
195
 * milliseconds. The longest backoff period is approximately
196
 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
197
 */
198
0
#define INITIAL_BACKOFF_MS 1L
199
0
#define BACKOFF_MAX_MULTIPLIER 1000
200
201
/*
202
 * Try locking path, retrying with quadratic backoff for at least
203
 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
204
 * exactly once. If timeout_ms is -1, try indefinitely.
205
 */
206
static int lock_file_timeout(struct repository *r, struct lock_file *lk,
207
           const char *path, int flags, long timeout_ms,
208
           int mode)
209
0
{
210
0
  int n = 1;
211
0
  int multiplier = 1;
212
0
  long remaining_ms = 0;
213
0
  static int random_initialized = 0;
214
215
0
  if (timeout_ms == 0)
216
0
    return lock_file(r, lk, path, flags, mode);
217
218
0
  if (!random_initialized) {
219
0
    srand((unsigned int)getpid());
220
0
    random_initialized = 1;
221
0
  }
222
223
0
  if (timeout_ms > 0)
224
0
    remaining_ms = timeout_ms;
225
226
0
  while (1) {
227
0
    long backoff_ms, wait_ms;
228
0
    int fd;
229
230
0
    fd = lock_file(r, lk, path, flags, mode);
231
232
0
    if (fd >= 0)
233
0
      return fd; /* success */
234
0
    else if (errno != EEXIST)
235
0
      return -1; /* failure other than lock held */
236
0
    else if (timeout_ms > 0 && remaining_ms <= 0)
237
0
      return -1; /* failure due to timeout */
238
239
0
    backoff_ms = multiplier * INITIAL_BACKOFF_MS;
240
    /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
241
0
    wait_ms = (750 + rand() % 500) * backoff_ms / 1000;
242
0
    sleep_millisec(wait_ms);
243
0
    remaining_ms -= wait_ms;
244
245
    /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
246
0
    multiplier += 2*n + 1;
247
0
    if (multiplier > BACKOFF_MAX_MULTIPLIER)
248
0
      multiplier = BACKOFF_MAX_MULTIPLIER;
249
0
    else
250
0
      n++;
251
0
  }
252
0
}
253
254
void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
255
0
{
256
0
  if (err == EEXIST) {
257
0
    const char *abs_path = absolute_path(path);
258
0
    struct strbuf lock_path = STRBUF_INIT;
259
0
    struct strbuf pid_path = STRBUF_INIT;
260
0
    uintmax_t pid;
261
0
    int pid_status = 0; /* 0 = unknown, 1 = running, -1 = stale */
262
263
0
    get_lock_path(&lock_path, abs_path);
264
0
    get_pid_path(&pid_path, abs_path);
265
266
0
    strbuf_addf(buf, _("Unable to create '%s': %s.\n\n"),
267
0
          lock_path.buf, strerror(err));
268
269
    /*
270
     * Try to read PID file unconditionally - it may exist if
271
     * core.lockfilePid was enabled.
272
     */
273
0
    if (!read_lock_pid(pid_path.buf, &pid)) {
274
0
      if (kill((pid_t)pid, 0) == 0 || errno == EPERM)
275
0
        pid_status = 1;  /* running (or no permission to signal) */
276
0
      else if (errno == ESRCH)
277
0
        pid_status = -1; /* no such process - stale lock */
278
0
    }
279
280
0
    if (pid_status == 1)
281
0
      strbuf_addf(buf, _("Lock may be held by process %" PRIuMAX "; "
282
0
             "if no git process is running, the lock file "
283
0
             "may be stale (PIDs can be reused)"),
284
0
            pid);
285
0
    else if (pid_status == -1)
286
0
      strbuf_addf(buf, _("Lock was held by process %" PRIuMAX ", "
287
0
             "which is no longer running; the lock file "
288
0
             "appears to be stale"),
289
0
            pid);
290
0
    else
291
0
      strbuf_addstr(buf, _("Another git process seems to be running in this repository, "
292
0
               "or the lock file may be stale"));
293
294
0
    strbuf_release(&lock_path);
295
0
    strbuf_release(&pid_path);
296
0
  } else {
297
0
    strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
298
0
          absolute_path(path), strerror(err));
299
0
  }
300
0
}
301
302
NORETURN void unable_to_lock_die(const char *path, int err)
303
0
{
304
0
  struct strbuf buf = STRBUF_INIT;
305
306
0
  unable_to_lock_message(path, err, &buf);
307
0
  die("%s", buf.buf);
308
0
}
309
310
/* This should return a meaningful errno on failure */
311
int hold_lock_file_for_update_timeout_mode(struct lock_file *lk,
312
             const char *path, int flags,
313
             long timeout_ms, int mode)
314
0
{
315
0
  return repo_hold_lock_file_for_update_timeout_mode(the_repository,
316
0
                 lk, path, flags,
317
0
                 timeout_ms, mode);
318
0
}
319
320
int repo_hold_lock_file_for_update_timeout_mode(struct repository *r,
321
            struct lock_file *lk,
322
            const char *path, int flags,
323
            long timeout_ms, int mode)
324
0
{
325
0
  int fd = lock_file_timeout(r, lk, path, flags, timeout_ms, mode);
326
0
  if (fd < 0) {
327
0
    if (flags & LOCK_DIE_ON_ERROR)
328
0
      unable_to_lock_die(path, errno);
329
0
    if (flags & LOCK_REPORT_ON_ERROR) {
330
0
      struct strbuf buf = STRBUF_INIT;
331
0
      unable_to_lock_message(path, errno, &buf);
332
0
      error("%s", buf.buf);
333
0
      strbuf_release(&buf);
334
0
    }
335
0
  }
336
0
  return fd;
337
0
}
338
339
char *get_locked_file_path(struct lock_file *lk)
340
0
{
341
0
  struct strbuf ret = STRBUF_INIT;
342
343
0
  strbuf_addstr(&ret, get_tempfile_path(lk->tempfile));
344
0
  if (ret.len <= LOCK_SUFFIX_LEN ||
345
0
      strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
346
0
    BUG("get_locked_file_path() called for malformed lock object");
347
  /* remove ".lock": */
348
0
  strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN);
349
0
  return strbuf_detach(&ret, NULL);
350
0
}
351
352
int commit_lock_file(struct lock_file *lk)
353
0
{
354
0
  char *result_path = get_locked_file_path(lk);
355
356
0
  delete_tempfile(&lk->pid_tempfile);
357
358
0
  if (commit_lock_file_to(lk, result_path)) {
359
0
    int save_errno = errno;
360
0
    free(result_path);
361
0
    errno = save_errno;
362
0
    return -1;
363
0
  }
364
0
  free(result_path);
365
0
  return 0;
366
0
}
367
368
int rollback_lock_file(struct lock_file *lk)
369
0
{
370
0
  delete_tempfile(&lk->pid_tempfile);
371
0
  return delete_tempfile(&lk->tempfile);
372
0
}