157
return lk->fd;
158
}
159
160
+static int sleep_microseconds(long us)
161
+{
162
+ struct timeval tv;
163
+ tv.tv_sec = 0;
164
+ tv.tv_usec = us;
165
+ return select(0, NULL, NULL, NULL, &tv);
166
+}
167
+
168
+/*
169
+ * Constants defining the gaps between attempts to lock a file. The
170
+ * first backoff period is approximately INITIAL_BACKOFF_MS
171
+ * milliseconds. The longest backoff period is approximately
172
+ * (BACKOFF_MAX_MULTIPLIER * INITIAL_BACKOFF_MS) milliseconds.
173
+ */
174
+#define INITIAL_BACKOFF_MS 1L
175
+#define BACKOFF_MAX_MULTIPLIER 1000
176
+
177
+/*
178
+ * Try locking path, retrying with quadratic backoff for at least
179
+ * timeout_ms milliseconds. If timeout_ms is 0, try locking the file
180
+ * exactly once. If timeout_ms is -1, try indefinitely.
181
+ */
182
+static int lock_file_timeout(struct lock_file *lk, const char *path,
183
+ int flags, long timeout_ms)
184
+{
185
+ int n = 1;
186
+ int multiplier = 1;
187
+ long remaining_us = 0;
188
+ static int random_initialized = 0;
189
+
190
+ if (timeout_ms == 0)
191
+ return lock_file(lk, path, flags);
192
+
193
+ if (!random_initialized) {
194
+ srandom((unsigned int)getpid());
195
+ random_initialized = 1;
196
+ }
197
+
198
+ if (timeout_ms > 0) {
199
+ /* avoid overflow */
200
+ if (timeout_ms <= LONG_MAX / 1000)
201
+ remaining_us = timeout_ms * 1000;
202
+ else
203
+ remaining_us = LONG_MAX;
204
+ }
205
+
206
+ while (1) {
207
+ long backoff_ms, wait_us;
208
+ int fd;
209
+
210
+ fd = lock_file(lk, path, flags);
211
+
212
+ if (fd >= 0)
213
+ return fd; /* success */
214
+ else if (errno != EEXIST)
215
+ return -1; /* failure other than lock held */
216
+ else if (timeout_ms > 0 && remaining_us <= 0)
217
+ return -1; /* failure due to timeout */
218
+
219
+ backoff_ms = multiplier * INITIAL_BACKOFF_MS;
220
+ /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */
221
+ wait_us = (750 + random() % 500) * backoff_ms;
222
+ sleep_microseconds(wait_us);
223
+ remaining_us -= wait_us;
224
+
225
+ /* Recursion: (n+1)^2 = n^2 + 2n + 1 */
226
+ multiplier += 2*n + 1;
227
+ if (multiplier > BACKOFF_MAX_MULTIPLIER)
228
+ multiplier = BACKOFF_MAX_MULTIPLIER;
229
+ else
230
+ n++;
231
+ }
232
+}
233
+
234
void unable_to_lock_message(const char *path, int err, struct strbuf *buf)
235
{
236
if (err == EEXIST) {
253
}
254
255
/* This should return a meaningful errno on failure */
182
-int hold_lock_file_for_update(struct lock_file *lk, const char *path, int flags)
256
+int hold_lock_file_for_update_timeout(struct lock_file *lk, const char *path,
257
+ int flags, long timeout_ms)
258
{
184
- int fd = lock_file(lk, path, flags);
259
+ int fd = lock_file_timeout(lk, path, flags, timeout_ms);
260
if (fd < 0 && (flags & LOCK_DIE_ON_ERROR))
261
unable_to_lock_die(path, errno);
262
return fd;