From 1e9676ec0a771de06abca3009eb4bdc5a4ae3312 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 5 Jun 2015 21:45:04 +0200 Subject: [PATCH 1/4] lockfile: replace random() by rand() On Windows, we do not have functions srandom() and random(). Use srand() and rand(). These functions produce random numbers of lesser quality, but for the purpose (a retry time-out) they are still good enough. Signed-off-by: Johannes Sixt Reviewed-by: Michael Haggerty Signed-off-by: Junio C Hamano --- lockfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lockfile.c b/lockfile.c index 30e65e9d22..738f20248f 100644 --- a/lockfile.c +++ b/lockfile.c @@ -191,7 +191,7 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, return lock_file(lk, path, flags); if (!random_initialized) { - srandom((unsigned int)getpid()); + srand((unsigned int)getpid()); random_initialized = 1; } @@ -218,7 +218,7 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, backoff_ms = multiplier * INITIAL_BACKOFF_MS; /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */ - wait_us = (750 + random() % 500) * backoff_ms; + wait_us = (750 + rand() % 500) * backoff_ms; sleep_microseconds(wait_us); remaining_us -= wait_us; From 2024d3176536fd437b4c0a744161e96bc150a24e Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 5 Jun 2015 21:45:05 +0200 Subject: [PATCH 2/4] help.c: wrap wait-only poll() invocation in sleep_millisec() We want to use the new function elsewhere in a moment. Signed-off-by: Johannes Sixt Reviewed-by: Michael Haggerty Signed-off-by: Junio C Hamano --- cache.h | 1 + help.c | 2 +- wrapper.c | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cache.h b/cache.h index 54f108a28f..328cdb73ee 100644 --- a/cache.h +++ b/cache.h @@ -1680,5 +1680,6 @@ int stat_validity_check(struct stat_validity *sv, const char *path); void stat_validity_update(struct stat_validity *sv, int fd); int versioncmp(const char *s1, const char *s2); +void sleep_millisec(int millisec); #endif /* CACHE_H */ diff --git a/help.c b/help.c index 2072a873e2..de1279b422 100644 --- a/help.c +++ b/help.c @@ -372,7 +372,7 @@ const char *help_unknown_cmd(const char *cmd) if (autocorrect > 0) { fprintf_ln(stderr, _("in %0.1f seconds automatically..."), (float)autocorrect/10.0); - poll(NULL, 0, autocorrect * 100); + sleep_millisec(autocorrect * 100); } return assumed; } diff --git a/wrapper.c b/wrapper.c index c1a663fd59..ff49807948 100644 --- a/wrapper.c +++ b/wrapper.c @@ -595,3 +595,8 @@ int write_file(const char *path, int fatal, const char *fmt, ...) } return 0; } + +void sleep_millisec(int millisec) +{ + poll(NULL, 0, millisec); +} From a8a17756bbc9617ba22d0c78a73fce5bb2faa6f2 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 5 Jun 2015 21:45:06 +0200 Subject: [PATCH 3/4] lockfile: convert retry timeout computations to millisecond When the goal is to wait for some random amount of time up to one second, it is not necessary to compute with microsecond precision. This is a preparation to re-use sleep_millisec(). Signed-off-by: Johannes Sixt Reviewed-by: Michael Haggerty Signed-off-by: Junio C Hamano --- lockfile.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/lockfile.c b/lockfile.c index 738f20248f..3f5b699cf7 100644 --- a/lockfile.c +++ b/lockfile.c @@ -184,7 +184,7 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, { int n = 1; int multiplier = 1; - long remaining_us = 0; + long remaining_ms = 0; static int random_initialized = 0; if (timeout_ms == 0) @@ -195,16 +195,11 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, random_initialized = 1; } - if (timeout_ms > 0) { - /* avoid overflow */ - if (timeout_ms <= LONG_MAX / 1000) - remaining_us = timeout_ms * 1000; - else - remaining_us = LONG_MAX; - } + if (timeout_ms > 0) + remaining_ms = timeout_ms; while (1) { - long backoff_ms, wait_us; + long backoff_ms, wait_ms; int fd; fd = lock_file(lk, path, flags); @@ -213,14 +208,14 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, return fd; /* success */ else if (errno != EEXIST) return -1; /* failure other than lock held */ - else if (timeout_ms > 0 && remaining_us <= 0) + else if (timeout_ms > 0 && remaining_ms <= 0) 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 */ - wait_us = (750 + rand() % 500) * backoff_ms; - sleep_microseconds(wait_us); - remaining_us -= wait_us; + wait_ms = (750 + rand() % 500) * backoff_ms / 1000; + sleep_microseconds(wait_ms*1000); + remaining_ms -= wait_ms; /* Recursion: (n+1)^2 = n^2 + 2n + 1 */ multiplier += 2*n + 1; From 30f8160d26f11156a6792565fe694c813406b929 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Fri, 5 Jun 2015 21:45:07 +0200 Subject: [PATCH 4/4] lockfile: wait using sleep_millisec() instead of select() Use the new function sleep_millisec() to delay execution for a short time. This avoids the invocation of select() with just a timeout, but no file descriptors. Such a use of select() is quit with EINVAL on Windows, leading to no delay at all. Signed-off-by: Johannes Sixt Reviewed-by: Michael Haggerty Signed-off-by: Junio C Hamano --- lockfile.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/lockfile.c b/lockfile.c index 3f5b699cf7..fb78bda495 100644 --- a/lockfile.c +++ b/lockfile.c @@ -157,14 +157,6 @@ static int lock_file(struct lock_file *lk, const char *path, int flags) return lk->fd; } -static int sleep_microseconds(long us) -{ - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = us; - return select(0, NULL, NULL, NULL, &tv); -} - /* * Constants defining the gaps between attempts to lock a file. The * first backoff period is approximately INITIAL_BACKOFF_MS @@ -214,7 +206,7 @@ static int lock_file_timeout(struct lock_file *lk, const char *path, backoff_ms = multiplier * INITIAL_BACKOFF_MS; /* back off for between 0.75*backoff_ms and 1.25*backoff_ms */ wait_ms = (750 + rand() % 500) * backoff_ms / 1000; - sleep_microseconds(wait_ms*1000); + sleep_millisec(wait_ms); remaining_ms -= wait_ms; /* Recursion: (n+1)^2 = n^2 + 2n + 1 */