8000 Introduce timeouts on sockets by ethomson · Pull Request #6535 · libgit2/libgit2 · GitHub
[go: up one dir, main page]

Skip to content

Introduce timeouts on sockets #6535

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
util: make monotonic time fn return ms
`git__timer` is now `git_time_monotonic`, and returns milliseconds
since an arbitrary epoch.

Using a floating point to store the number of seconds elapsed was
clever, as it better supports the wide range of precision from the
different monotonic clocks of different systems. But we're a version
control system, not a real-time clock.

Milliseconds is a good enough precision for our work _and_ it's the
units that system calls like `poll` take and that our users interact
with.

Make `git_time_monotonic` return the monotonically increasing number
of milliseconds "ticked" since some arbitrary epoch.
  • Loading branch information
ethomson committed May 13, 2023
commit 6c0d5b11c05254d91a2d0025d556251404f8f05f
17 changes: 9 additions & 8 deletions src/cli/progress.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
/*
* Show updates to the percentage and number of objects received
* separately from the throughput to give an accurate progress while
* avoiding too much noise on the screen.
* avoiding too much noise on the screen. (In milliseconds.)
*/
#define PROGRESS_UPDATE_TIME 0.10
#define THROUGHPUT_UPDATE_TIME 1.00
#define PROGRESS_UPDATE_TIME 60
#define THROUGHPUT_UPDATE_TIME 500

#define is_nl(c) ((c) == '\r' || (c) == '\n')

Expand Down Expand Up @@ -54,7 +54,7 @@ static int progress_write(cli_progress *progress, bool force, git_str *line)
bool has_nl;
size_t no_nl = no_nl_len(line->ptr, line->size);
size_t nl = nl_len(&has_nl, line->ptr + no_nl, line->size - no_nl);
double now = git__timer();
uint64_t now = git_time_monotonic();
size_t i;

/* Avoid spamming the console with progress updates */
Expand Down Expand Up @@ -191,20 +191,21 @@ static int fetch_receiving(
{
char *recv_units[] = { "B", "KiB", "MiB", "GiB", "TiB", NULL };
char *rate_units[] = { "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", NULL };
uint64_t now, elapsed;

double now, recv_len, rate, elapsed;
double recv_len, rate;
size_t recv_unit_idx = 0, rate_unit_idx = 0;
bool done = (stats->received_objects == stats->total_objects);

if (!progress->action_start)
progress->action_start = git__timer();
progress->action_start = git_time_monotonic();

if (done && progress->action_finish)
now = progress->action_finish;
else if (done)
progress->action_finish = now = git__timer();
progress->action_finish = now = git_time_monotonic();
else
now = git__timer();
now = git_time_monotonic();

if (progress->throughput_update &&
now - progress->throughput_update < THROUGHPUT_UPDATE_TIME) {
Expand Down
8 changes: 4 additions & 4 deletions src/cli/progress.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ typedef struct {
cli_progress_t action;

/* Actions may time themselves (eg fetch) but are not required to */
double action_start;
double action_finish;
uint64_t action_start;
uint64_t action_finish;

/* Last console update, avoid too frequent updates. */
double last_update;
uint64_t last_update;

/* Accumulators for partial output and deferred updates. */
git_str sideband;
git_str onscreen;
git_str deferred;

/* Last update about throughput */
double throughput_update;
uint64_t throughput_update;
double throughput_bytes;
} cli_progress;

Expand Down
12 changes: 6 additions & 6 deletions src/libgit2/pack-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid,
pb->done = false;

if (pb->progress_cb) {
double current_time = git__timer();
double elapsed = current_time - pb->last_progress_report_time;
uint64_t current_time = git_time_monotonic();
uint64_t elapsed = current_time - pb->last_progress_report_time;

if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
pb->last_progress_report_time = current_time;

ret = pb->progress_cb(
Expand Down Expand Up @@ -934,10 +934,10 @@ static int report_delta_progress(
int ret;

if (pb->progress_cb) {
double current_time = git__timer();
double elapsed = current_time - pb->last_progress_report_time;
uint64_t current_time = git_time_monotonic();
uint64_t elapsed = current_time - pb->last_progress_report_time;

if (force || elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
if (force || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
pb->last_progress_report_time = current_time;

ret = pb->progress_cb(
Expand Down
4 changes: 3 additions & 1 deletion src/libgit2/pack-objects.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ struct git_packbuilder {

git_packbuilder_progress progress_cb;
void *progress_cb_payload;
double last_progress_report_time; /* the time progress was last reported */

/* the time progress was last reported, in millisecond ticks */
uint64_t last_progress_report_time;

bool done;
};
Expand Down
8 changes: 4 additions & 4 deletions src/libgit2/transports/smart_protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ struct push_packbuilder_payload
git_push_transfer_progress_cb cb;
void *cb_payload;
size_t last_bytes;
double last_progress_report_time;
uint64_t last_progress_report_time;
};

static int stream_thunk(void *buf, size_t size, void *data)
Expand All @@ -1126,11 +1126,11 @@ static int stream_thunk(void *buf, size_t size, void *data)
return error;

if (payload->cb) {
double current_time = git__timer();
double elapsed = current_time - payload->last_progress_report_time;
uint64_t current_time = git_time_monotonic();
uint64_t elapsed = current_time - payload->last_progress_report_time;
payload->last_bytes += size;

if (elapsed < 0 || elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
if (elapsed >= MIN_PROGRESS_UPDATE_INTERVAL) {
payload->last_progress_report_time = current_time;
error = payload->cb(payload->pb->nr_written, payload->pb->nr_objects, payload->last_bytes, payload->cb_payload);
}
Expand Down
10 changes: 6 additions & 4 deletions src/util/rand.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ GIT_INLINE(int) getseed(uint64_t *seed)
HCRYPTPROV provider;
SYSTEMTIME systemtime;
FILETIME filetime, idletime, kerneltime, usertime;
bits convert;

if (CryptAcquireContext(&provider, 0, 0, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) {
Expand Down Expand Up @@ -67,7 +66,7 @@ GIT_INLINE(int) getseed(uint64_t *seed)
*seed ^= ((uint64_t)GetCurrentProcessId() << 32);
*seed ^= ((uint64_t)GetCurrentThreadId() << 48);

convert.f = git__timer(); *seed ^= (convert.d);
*seed ^= git_time_monotonic();

/* Mix in the addresses of some functions and variables */
*seed ^= (((uint64_t)((uintptr_t)seed) << 32));
Expand All @@ -82,9 +81,12 @@ GIT_INLINE(int) getseed(uint64_t *seed)
{
struct timeval tv;
double loadavg[3];
bits convert;
int fd;

# if defined(GIT_RAND_GETLOADAVG)
bits convert;
# endif

# if defined(GIT_RAND_GETENTROPY)
GIT_UNUSED((fd = 0));

Expand Down Expand Up @@ -131,7 +133,7 @@ GIT_INLINE(int) getseed(uint64_t *seed)
GIT_UNUSED(loadavg[0]);
# endif

convert.f = git__timer(); *seed ^= (convert.d);
*seed ^= git_time_monotonic();

/* Mix in the addresses of some variables */
*seed ^= ((uint64_t)((size_t)((void *)seed)) << 32);
Expand Down
40 changes: 24 additions & 16 deletions src/util/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,59 +319,67 @@ GIT_INLINE(void) git__memzero(void *data, size_t size)

#ifdef GIT_WIN32

GIT_INLINE(double) git__timer(void)
GIT_INLINE(uint64_t) git_time_monotonic(void)
{
/* GetTickCount64 returns the number of milliseconds that have
* elapsed since the system was started. */
return (double) GetTickCount64() / (double) 1000;
return GetTickCount64();
}

#elif __APPLE__

#include <mach/mach_time.h>
#include <sys/time.h>

GIT_INLINE(double) git__timer(void)
GIT_INLINE(uint64_t) git_time_monotonic(void)
{
uint64_t time = mach_absolute_time();
static double scaling_factor = 0;
static double scaling_factor = 0;

if (scaling_factor == 0) {
mach_timebase_info_data_t info;

if (scaling_factor == 0) {
mach_timebase_info_data_t info;
(void)mach_timebase_info(&info);
scaling_factor = (double)info.numer / (double)info.denom;
}
scaling_factor = mach_timebase_info(&info) == KERN_SUCCESS ?
((double)info.numer / (double)info.denom) / 1.0E6 :
-1;
} else if (scaling_factor < 0) {
struct timeval tv;

/* mach_timebase_info failed; fall back to gettimeofday */
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}

return (double)time * scaling_factor / 1.0E9;
return (uint64_t)(mach_absolute_time() * scaling_factor);
}

#elif defined(__amigaos4__)

#include <proto/timer.h>

GIT_INLINE(double) git__timer(void)
GIT_INLINE(uint64_t) git_time_monotonic(void)
{
struct TimeVal tv;
ITimer->GetUpTime(&tv);
return (double)tv.Seconds + (double)tv.Microseconds / 1.0E6;
return (tv.Seconds * 1000) + (tv.Microseconds / 1000);
}

#else

#include <sys/time.h>

GIT_INLINE(double) git__timer(void)
GIT_INLINE(uint64_t) git_time_monotonic(void)
{
struct timeval tv;

#ifdef CLOCK_MONOTONIC
struct timespec tp;
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
return (double) tp.tv_sec + (double) tp.tv_nsec / 1.0E9;
return (tp.tv_sec * 1000) + (tp.tv_nsec / 1.0E6);
#endif

/* Fall back to using gettimeofday */
gettimeofday(&tv, NULL);
return (double)tv.tv_sec + (double)tv.tv_usec / 1.0E6;
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
}

#endif
Expand Down
8 changes: 4 additions & 4 deletions tests/clar/clar_libgit2_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,23 @@ void cl_perf_timer__init(cl_perf_timer *t)

void cl_perf_timer__start(cl_perf_timer *t)
{
t->time_started = git__timer();
t->time_started = git_time_monotonic();
}

void cl_perf_timer__stop(cl_perf_timer *t)
{
double time_now = git__timer();
uint64_t time_now = git_time_monotonic();

t->last = time_now - t->time_started;
t->sum += t->last;
}

double cl_perf_timer__last(const cl_perf_timer *t)
uint64_t cl_perf_timer__last(const cl_perf_timer *t)
{
return t->last;
}

double cl_perf_timer__sum(const cl_perf_timer *t)
uint64_t cl_perf_timer__sum(const cl_perf_timer *t)
{
return t->sum;
}
10 changes: 5 additions & 5 deletions tests/clar/clar_libgit2_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
struct cl_perf_timer
{
/* cumulative running time across all start..stop intervals */
double sum;
uint64_t sum;

/* value of last start..stop interval */
double last;
uint64_t last;

/* clock value at start */
double time_started;
uint64_t time_started;
};

#define CL_PERF_TIMER_INIT {0}
Expand All @@ -24,12 +24,12 @@ void cl_perf_timer__stop(cl_perf_timer *t);
/**
* return value of last start..stop interval in seconds.
*/
double cl_perf_timer__last(const cl_perf_timer *t);
uint64_t cl_perf_timer__last(const cl_perf_timer *t);

/**
* return cumulative running time across all start..stop
* intervals in seconds.
*/
double cl_perf_timer__sum(const cl_perf_timer *t);
uint64_t cl_perf_timer__sum(const cl_perf_timer *t);

#endif /* __CLAR_LIBGIT2_TIMER__ */
2 changes: 1 addition & 1 deletion tests/clar/clar_libgit2_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ static void _cl_trace_cb__event_handler(

case CL_TRACE__TEST__END:
cl_perf_timer__stop(&s_timer_test);
git_trace(GIT_TRACE_TRACE, "%s::%s: End Test (%.3f %.3f)", suite_name, test_name,
git_trace(GIT_TRACE_TRACE, "%s::%s: End Test (%" PRIuZ " %" PRIuZ ")", suite_name, test_name,
cl_perf_timer__last(&s_timer_run),
cl_perf_timer__last(&s_timer_test));
break;
Expand Down
0