* 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. */
| 201 | * exactly once. If timeout_ms is -1, try indefinitely. |
| 202 | */ |
| 203 | static int lock_file_timeout(struct lock_file *lk, const char *path, |
| 204 | int flags, long timeout_ms, int mode) |
| 205 | { |
| 206 | int n = 1; |
| 207 | int multiplier = 1; |
| 208 | long remaining_ms = 0; |
| 209 | static int random_initialized = 0; |
| 210 | |
| 211 | if (timeout_ms == 0) |
| 212 | return lock_file(lk, path, flags, mode); |
| 213 | |
| 214 | if (!random_initialized) { |
| 215 | srand((unsigned int)getpid()); |
| 216 | random_initialized = 1; |
| 217 | } |
| 218 | |
| 219 | if (timeout_ms > 0) |
| 220 | remaining_ms = timeout_ms; |
| 221 | |
| 222 | while (1) { |
| 223 | long backoff_ms, wait_ms; |
| 224 | int fd; |
| 225 | |
| 226 | fd = lock_file(lk, path, flags, mode); |
| 227 | |
| 228 | if (fd >= 0) |
| 229 | return fd; /* success */ |
| 230 | else if (errno != EEXIST) |
| 231 | return -1; /* failure other than lock held */ |
| 232 | else if (timeout_ms > 0 && remaining_ms <= 0) |
| 233 | return -1; /* failure due to timeout */ |
| 234 | |
| 235 | backoff_ms = multiplier * INITIAL_BACKOFF_MS; |
| 236 | /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */ |
| 237 | wait_ms = (750 + rand() % 500) * backoff_ms / 1000; |
| 238 | sleep_millisec(wait_ms); |
| 239 | remaining_ms -= wait_ms; |
| 240 | |
| 241 | /* Recursion: (n+1)^2 = n^2 + 2n + 1 */ |
| 242 | multiplier += 2*n + 1; |
| 243 | if (multiplier > BACKOFF_MAX_MULTIPLIER) |
| 244 | multiplier = BACKOFF_MAX_MULTIPLIER; |
| 245 | else |
| 246 | n++; |
| 247 | } |
| 248 | } |
| 249 | |
| 250 | void unable_to_lock_message(const char *path, int err, struct strbuf *buf) |
| 251 | { |
no test coverage detected