lockfile.c 5.57 KB
Newer Older
1 2 3
/*
 * Copyright (c) 2005, Junio C Hamano
 */
4

5
#include "cache.h"
6
#include "lockfile.h"
7

8
/*
9
 * path = absolute or relative path name
10
 *
11 12 13
 * Remove the last path name element from path (leaving the preceding
 * "/", if any).  If path is empty or the root directory ("/"), set
 * path to the empty string.
14
 */
15
static void trim_last_path_component(struct strbuf *path)
16
{
17
	int i = path->len;
18 19

	/* back up past trailing slashes, if any */
20 21
	while (i && path->buf[i - 1] == '/')
		i--;
22 23

	/*
24 25
	 * then go backwards until a slash, or the beginning of the
	 * string
26
	 */
27 28 29 30
	while (i && path->buf[i - 1] != '/')
		i--;

	strbuf_setlen(path, i);
31 32 33 34 35 36 37
}


/* We allow "recursive" symbolic links. Only within reason, though */
#define MAXDEPTH 5

/*
38
 * path contains a path that might be a symlink.
39
 *
40 41 42
 * If path is a symlink, attempt to overwrite it with a path to the
 * real file or directory (which may or may not exist), following a
 * chain of symlinks if necessary.  Otherwise, leave path unmodified.
43
 *
44 45 46
 * This is a best-effort routine.  If an error occurs, path will
 * either be left unmodified or will name a different symlink in a
 * symlink chain that started with the original path.
47
 */
48
static void resolve_symlink(struct strbuf *path)
49 50
{
	int depth = MAXDEPTH;
51
	static struct strbuf link = STRBUF_INIT;
52 53

	while (depth--) {
54
		if (strbuf_readlink(&link, path->buf, path->len) < 0)
55
			break;
56

57
		if (is_absolute_path(link.buf))
58
			/* absolute path simply replaces p */
59
			strbuf_reset(path);
60
		else
61
			/*
62
			 * link is a relative path, so replace the
63 64
			 * last element of p with it.
			 */
65
			trim_last_path_component(path);
66 67

		strbuf_addbuf(path, &link);
68
	}
69
	strbuf_reset(&link);
70 71
}

72
/* Make sure errno contains a meaningful value on error */
73
static int lock_file(struct lock_file *lk, const char *path, int flags)
74
{
75
	struct strbuf filename = STRBUF_INIT;
76

77 78 79
	strbuf_addstr(&filename, path);
	if (!(flags & LOCK_NO_DEREF))
		resolve_symlink(&filename);
80

81
	strbuf_addstr(&filename, LOCK_SUFFIX);
82
	lk->tempfile = create_tempfile(filename.buf);
83
	strbuf_release(&filename);
84
	return lk->tempfile ? lk->tempfile->fd : -1;
85 86
}

87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/*
 * Constants defining the gaps between attempts to lock a file. The
 * first backoff period is approximately INITIAL_BACKOFF_MS
 * milliseconds. The longest backoff period is approximately
 * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
 */
#define INITIAL_BACKOFF_MS 1L
#define BACKOFF_MAX_MULTIPLIER 1000

/*
 * Try locking path, retrying with quadratic backoff for at least
 * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
 * exactly once. If timeout_ms is -1, try indefinitely.
 */
static int lock_file_timeout(struct lock_file *lk, const char *path,
			     int flags, long timeout_ms)
{
	int n = 1;
	int multiplier = 1;
106
	long remaining_ms = 0;
107 108 109 110 111 112
	static int random_initialized = 0;

	if (timeout_ms == 0)
		return lock_file(lk, path, flags);

	if (!random_initialized) {
113
		srand((unsigned int)getpid());
114 115 116
		random_initialized = 1;
	}

117 118
	if (timeout_ms > 0)
		remaining_ms = timeout_ms;
119 120

	while (1) {
121
		long backoff_ms, wait_ms;
122 123 124 125 126 127 128 129
		int fd;

		fd = lock_file(lk, path, flags);

		if (fd >= 0)
			return fd; /* success */
		else if (errno != EEXIST)
			return -1; /* failure other than lock held */
130
		else if (timeout_ms > 0 && remaining_ms <= 0)
131 132 133 134
			return -1; /* failure due to timeout */

		backoff_ms = multiplier * INITIAL_BACKOFF_MS;
		/* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
135
		wait_ms = (750 + rand() % 500) * backoff_ms / 1000;
136
		sleep_millisec(wait_ms);
137
		remaining_ms -= wait_ms;
138 139 140 141 142 143 144 145 146 147

		/* Recursion: (n+1)^2 = n^2 + 2n + 1 */
		multiplier += 2*n + 1;
		if (multiplier > BACKOFF_MAX_MULTIPLIER)
			multiplier = BACKOFF_MAX_MULTIPLIER;
		else
			n++;
	}
}

148
void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
149
{
150
	if (err == EEXIST) {
151
		strbuf_addf(buf, _("Unable to create '%s.lock': %s.\n\n"
152 153 154 155 156
		    "Another git process seems to be running in this repository, e.g.\n"
		    "an editor opened by 'git commit'. Please make sure all processes\n"
		    "are terminated then try again. If it still fails, a git process\n"
		    "may have crashed in this repository earlier:\n"
		    "remove the file manually to continue."),
157
			    absolute_path(path), strerror(err));
158
	} else
159
		strbuf_addf(buf, _("Unable to create '%s.lock': %s"),
160
			    absolute_path(path), strerror(err));
161 162
}

163
NORETURN void unable_to_lock_die(const char *path, int err)
164
{
165 166 167 168
	struct strbuf buf = STRBUF_INIT;

	unable_to_lock_message(path, err, &buf);
	die("%s", buf.buf);
169 170
}

171
/* This should return a meaningful errno on failure */
172 173
int hold_lock_file_for_update_timeout(struct lock_file *lk, const char *path,
				      int flags, long timeout_ms)
174
{
175
	int fd = lock_file_timeout(lk, path, flags, timeout_ms);
176 177 178 179 180 181 182 183 184 185
	if (fd < 0) {
		if (flags & LOCK_DIE_ON_ERROR)
			unable_to_lock_die(path, errno);
		if (flags & LOCK_REPORT_ON_ERROR) {
			struct strbuf buf = STRBUF_INIT;
			unable_to_lock_message(path, errno, &buf);
			error("%s", buf.buf);
			strbuf_release(&buf);
		}
	}
186 187 188
	return fd;
}

189 190
char *get_locked_file_path(struct lock_file *lk)
{
191
	struct strbuf ret = STRBUF_INIT;
192

193
	strbuf_addstr(&ret, get_tempfile_path(lk->tempfile));
194 195
	if (ret.len <= LOCK_SUFFIX_LEN ||
	    strcmp(ret.buf + ret.len - LOCK_SUFFIX_LEN, LOCK_SUFFIX))
196
		BUG("get_locked_file_path() called for malformed lock object");
197
	/* remove ".lock": */
198 199
	strbuf_setlen(&ret, ret.len - LOCK_SUFFIX_LEN);
	return strbuf_detach(&ret, NULL);
200 201
}

202
int commit_lock_file(struct lock_file *lk)
203
{
204
	char *result_path = get_locked_file_path(lk);
205

206
	if (commit_lock_file_to(lk, result_path)) {
207
		int save_errno = errno;
208
		free(result_path);
209
		errno = save_errno;
210
		return -1;
211
	}
212
	free(result_path);
213
	return 0;
214
}