Skip to content

Commit 7d6126d

Browse files
ptarjangitster
authored andcommitted
fsmonitor: use pthread_cond_timedwait for cookie wait
The cookie wait in with_lock__wait_for_cookie() uses an infinite pthread_cond_wait() loop. The existing comment notes the desire to switch to pthread_cond_timedwait(), but the routine was not available in git thread-utils. On certain container or overlay filesystems, inotify watches may succeed but events are never delivered. In this case the daemon would hang indefinitely waiting for the cookie event, which in turn causes the client to hang. Replace the infinite wait with a one-second timeout using pthread_cond_timedwait(). If the timeout fires, report an error and let the client proceed with a trivial (full-scan) response rather than blocking forever. Signed-off-by: Paul Tarjan <github@paulisageek.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 4ffb00f commit 7d6126d

1 file changed

Lines changed: 24 additions & 13 deletions

File tree

builtin/fsmonitor--daemon.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -197,20 +197,31 @@ static enum fsmonitor_cookie_item_result with_lock__wait_for_cookie(
197197
unlink(cookie_pathname.buf);
198198

199199
/*
200-
* Technically, this is an infinite wait (well, unless another
201-
* thread sends us an abort). I'd like to change this to
202-
* use `pthread_cond_timedwait()` and return an error/timeout
203-
* and let the caller do the trivial response thing, but we
204-
* don't have that routine in our thread-utils.
205-
*
206-
* After extensive beta testing I'm not really worried about
207-
* this. Also note that the above open() and unlink() calls
208-
* will cause at least two FS events on that path, so the odds
209-
* of getting stuck are pretty slim.
200+
* Wait for the listener thread to observe the cookie file.
201+
* Time out after a short interval so that the client
202+
* does not hang forever if the filesystem does not deliver
203+
* events (e.g., on certain container/overlay filesystems
204+
* where inotify watches succeed but events never arrive).
210205
*/
211-
while (cookie->result == FCIR_INIT)
212-
pthread_cond_wait(&state->cookies_cond,
213-
&state->main_lock);
206+
{
207+
struct timeval now;
208+
struct timespec ts;
209+
int err = 0;
210+
211+
gettimeofday(&now, NULL);
212+
ts.tv_sec = now.tv_sec + 1;
213+
ts.tv_nsec = now.tv_usec * 1000;
214+
215+
while (cookie->result == FCIR_INIT && !err)
216+
err = pthread_cond_timedwait(&state->cookies_cond,
217+
&state->main_lock,
218+
&ts);
219+
if (err == ETIMEDOUT && cookie->result == FCIR_INIT) {
220+
trace_printf_key(&trace_fsmonitor,
221+
"cookie_wait timed out");
222+
cookie->result = FCIR_ERROR;
223+
}
224+
}
214225

215226
done:
216227
hashmap_remove(&state->cookies, &cookie->entry, NULL);

0 commit comments

Comments
 (0)