@@ -157,6 +157,80 @@ static int lock_file(struct lock_file *lk, const char *path, int flags)
157157 return lk -> fd ;
158158}
159159
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+
160234void unable_to_lock_message (const char * path , int err , struct strbuf * buf )
161235{
162236 if (err == EEXIST ) {
@@ -179,9 +253,10 @@ NORETURN void unable_to_lock_die(const char *path, int err)
179253}
180254
181255/* 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 )
183258{
184- int fd = lock_file (lk , path , flags );
259+ int fd = lock_file_timeout (lk , path , flags , timeout_ms );
185260 if (fd < 0 && (flags & LOCK_DIE_ON_ERROR ))
186261 unable_to_lock_die (path , errno );
187262 return fd ;
0 commit comments