]> git.ipfire.org Git - thirdparty/git.git/blame - lockfile.c
Merge branch 'jt/t5500-unflake'
[thirdparty/git.git] / lockfile.c
CommitLineData
021b6e45
JH
1/*
2 * Copyright (c) 2005, Junio C Hamano
3 */
2db69de8 4
021b6e45 5#include "cache.h"
697cc8ef 6#include "lockfile.h"
021b6e45 7
5d5a7a67 8/*
0c0d6e86 9 * path = absolute or relative path name
5d5a7a67 10 *
0c0d6e86
MH
11 * Remove the last path name element from path (leaving the preceding
12 * "/", if any). If path is empty or the root directory ("/"), set
13 * path to the empty string.
5d5a7a67 14 */
0c0d6e86 15static void trim_last_path_component(struct strbuf *path)
5d5a7a67 16{
0c0d6e86 17 int i = path->len;
5d5a7a67
BS
18
19 /* back up past trailing slashes, if any */
0c0d6e86
MH
20 while (i && path->buf[i - 1] == '/')
21 i--;
5d5a7a67
BS
22
23 /*
0c0d6e86
MH
24 * then go backwards until a slash, or the beginning of the
25 * string
5d5a7a67 26 */
0c0d6e86
MH
27 while (i && path->buf[i - 1] != '/')
28 i--;
29
30 strbuf_setlen(path, i);
5d5a7a67
BS
31}
32
33
34/* We allow "recursive" symbolic links. Only within reason, though */
35#define MAXDEPTH 5
36
37/*
6cad8053 38 * path contains a path that might be a symlink.
5d5a7a67 39 *
6cad8053
MH
40 * If path is a symlink, attempt to overwrite it with a path to the
41 * real file or directory (which may or may not exist), following a
42 * chain of symlinks if necessary. Otherwise, leave path unmodified.
5d5a7a67 43 *
6cad8053
MH
44 * This is a best-effort routine. If an error occurs, path will
45 * either be left unmodified or will name a different symlink in a
46 * symlink chain that started with the original path.
5d5a7a67 47 */
6cad8053 48static void resolve_symlink(struct strbuf *path)
5d5a7a67
BS
49{
50 int depth = MAXDEPTH;
5025d845 51 static struct strbuf link = STRBUF_INIT;
5d5a7a67
BS
52
53 while (depth--) {
6cad8053 54 if (strbuf_readlink(&link, path->buf, path->len) < 0)
5025d845 55 break;
5d5a7a67 56
6cad8053 57 if (is_absolute_path(link.buf))
5d5a7a67 58 /* absolute path simply replaces p */
6cad8053 59 strbuf_reset(path);
0c0d6e86 60 else
5d5a7a67 61 /*
5025d845 62 * link is a relative path, so replace the
5d5a7a67
BS
63 * last element of p with it.
64 */
0c0d6e86 65 trim_last_path_component(path);
6cad8053
MH
66
67 strbuf_addbuf(path, &link);
5d5a7a67 68 }
5025d845 69 strbuf_reset(&link);
5d5a7a67
BS
70}
71
447ff1bf 72/* Make sure errno contains a meaningful value on error */
fa3bff24
TB
73static int lock_file(struct lock_file *lk, const char *path, int flags,
74 int mode)
021b6e45 75{
1a9d15db 76 struct strbuf filename = STRBUF_INIT;
04e57d4d 77
1a9d15db
MH
78 strbuf_addstr(&filename, path);
79 if (!(flags & LOCK_NO_DEREF))
80 resolve_symlink(&filename);
fa137f67 81
1a9d15db 82 strbuf_addstr(&filename, LOCK_SUFFIX);
fa3bff24 83 lk->tempfile = create_tempfile_mode(filename.buf, mode);
1a9d15db 84 strbuf_release(&filename);
076aa2cb 85 return lk->tempfile ? lk->tempfile->fd : -1;
021b6e45
JH
86}
87
044b6a9e
MH
88/*
89 * Constants defining the gaps between attempts to lock a file. The
90 * first backoff period is approximately INITIAL_BACKOFF_MS
91 * milliseconds. The longest backoff period is approximately
92 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
93 */
94#define INITIAL_BACKOFF_MS 1L
95#define BACKOFF_MAX_MULTIPLIER 1000
96
97/*
98 * Try locking path, retrying with quadratic backoff for at least
99 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
100 * exactly once. If timeout_ms is -1, try indefinitely.
101 */
102static int lock_file_timeout(struct lock_file *lk, const char *path,
fa3bff24 103 int flags, long timeout_ms, int mode)
044b6a9e
MH
104{
105 int n = 1;
106 int multiplier = 1;
a8a17756 107 long remaining_ms = 0;
044b6a9e
MH
108 static int random_initialized = 0;
109
110 if (timeout_ms == 0)
fa3bff24 111 return lock_file(lk, path, flags, mode);
044b6a9e
MH
112
113 if (!random_initialized) {
1e9676ec 114 srand((unsigned int)getpid());
044b6a9e
MH
115 random_initialized = 1;
116 }
117
a8a17756
JS
118 if (timeout_ms > 0)
119 remaining_ms = timeout_ms;
044b6a9e
MH
120
121 while (1) {
a8a17756 122 long backoff_ms, wait_ms;
044b6a9e
MH
123 int fd;
124
fa3bff24 125 fd = lock_file(lk, path, flags, mode);
044b6a9e
MH
126
127 if (fd >= 0)
128 return fd; /* success */
129 else if (errno != EEXIST)
130 return -1; /* failure other than lock held */
a8a17756 131 else if (timeout_ms > 0 && remaining_ms <= 0)
044b6a9e
MH
132 return -1; /* failure due to timeout */
133
134 backoff_ms = multiplier * INITIAL_BACKOFF_MS;
135 /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
a8a17756 136 wait_ms = (750 + rand() % 500) * backoff_ms / 1000;
30f8160d 137 sleep_millisec(wait_ms);
a8a17756 138 remaining_ms -= wait_ms;
044b6a9e
MH
139
140 /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
141 multiplier += 2*n + 1;
142 if (multiplier > BACKOFF_MAX_MULTIPLIER)
143 multiplier = BACKOFF_MAX_MULTIPLIER;
144 else
145 n++;
146 }
147}
148
6af926e8 149void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
e43a6fd3 150{
bdfd739d 151 if (err == EEXIST) {
3030c295 152 strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n"
aed7480c
MM
153 "Another git process seems to be running in this repository, e.g.\n"
154 "an editor opened by 'git commit'. Please make sure all processes\n"
155 "are terminated then try again. If it still fails, a git process\n"
156 "may have crashed in this repository earlier:\n"
157 "remove the file manually to continue."),
e2a57aac 158 absolute_path(path), strerror(err));
1b018fd9 159 } else
3030c295 160 strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
e2a57aac 161 absolute_path(path), strerror(err));
1b018fd9
MV
162}
163
e197c218 164NORETURN void unable_to_lock_die(const char *path, int err)
1b018fd9 165{
6af926e8
RS
166 struct strbuf buf = STRBUF_INIT;
167
168 unable_to_lock_message(path, err, &buf);
169 die("%s", buf.buf);
e43a6fd3
MM
170}
171
447ff1bf 172/* This should return a meaningful errno on failure */
fa3bff24
TB
173int hold_lock_file_for_update_timeout_mode(struct lock_file *lk,
174 const char *path, int flags,
175 long timeout_ms, int mode)
40aaae88 176{
fa3bff24 177 int fd = lock_file_timeout(lk, path, flags, timeout_ms, mode);
3f061bf5
JH
178 if (fd < 0) {
179 if (flags & LOCK_DIE_ON_ERROR)
180 unable_to_lock_die(path, errno);
181 if (flags & LOCK_REPORT_ON_ERROR) {
182 struct strbuf buf = STRBUF_INIT;
183 unable_to_lock_message(path, errno, &buf);
184 error("%s", buf.buf);
185 strbuf_release(&buf);
186 }
187 }
40aaae88
JH
188 return fd;
189}
190
ec38b4e4
MH
191char *get_locked_file_path(struct lock_file *lk)
192{
1a9d15db 193 struct strbuf ret = STRBUF_INIT;
013870cd 194
076aa2cb 195 strbuf_addstr(&ret, get_tempfile_path(lk->tempfile));
1a9d15db
MH
196 if (ret.len <= LOCK_SUFFIX_LEN ||
197 strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
033abf97 198 BUG("get_locked_file_path() called for malformed lock object");
9c77381d 199 /* remove ".lock": */
1a9d15db
MH
200 strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN);
201 return strbuf_detach(&ret, NULL);
93dcaea2
JH
202}
203
751baced 204int commit_lock_file(struct lock_file *lk)
021b6e45 205{
9c77381d 206 char *result_path = get_locked_file_path(lk);
8a1c7533 207
9c77381d 208 if (commit_lock_file_to(lk, result_path)) {
1b1648f4 209 int save_errno = errno;
9c77381d 210 free(result_path);
1b1648f4 211 errno = save_errno;
d6cf61bf 212 return -1;
1b1648f4 213 }
9c77381d 214 free(result_path);
d6cf61bf 215 return 0;
021b6e45 216}