diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index b7987bc99a..61cbe91488 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -673,3 +673,33 @@ tor_gettimeofday_cache_set(const struct timeval *tv) #endif #endif +/** + * As tor_gettimeofday_cached, but can never move backwards in time. + * + * The returned value may diverge from wall-clock time, since wall-clock time + * can trivially be adjusted backwards, and this can't. Don't mix wall-clock + * time with these values in the same calculation. + * + * Depending on implementation, this function may or may not "smooth out" huge + * jumps forward in wall-clock time. It may or may not keep its results + * advancing forward (as opposed to stalling) if the wall-clock time goes + * backwards. The current implementation does neither of of these. + * + * This function is not thread-safe; do not call it outside the main thread. + * + * In future versions of Tor, this may return a time does not have its + * origin at the Unix epoch. + */ +void +tor_gettimeofday_cached_monotonic(struct timeval *tv) +{ + struct timeval last_tv = { 0, 0 }; + + tor_gettimeofday_cached(tv); + if (timercmp(tv, &last_tv, <)) { + memcpy(tv, &last_tv, sizeof(struct timeval)); + } else { + memcpy(&last_tv, tv, sizeof(struct timeval)); + } +} + diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index 17e0523789..f0d1828b7b 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -94,6 +94,7 @@ void tor_gettimeofday_cache_clear(void); #ifdef TOR_UNIT_TESTS void tor_gettimeofday_cache_set(const struct timeval *tv); #endif +void tor_gettimeofday_cached_monotonic(struct timeval *tv); #endif diff --git a/src/or/buffers.c b/src/or/buffers.c index 271964c5ac..87e8abffe9 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -680,7 +680,7 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped) chunk = chunk_new_with_alloc_size(preferred_chunk_size(capacity)); } - tor_gettimeofday_cached(&now); + tor_gettimeofday_cached_monotonic(&now); chunk->inserted_time = (uint32_t)tv_to_msec(&now); if (buf->tail) { diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 01d5aee60a..b2eb730c8c 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -1794,7 +1794,7 @@ circuits_handle_oom(size_t current_allocation) mem_to_recover = current_allocation - mem_target; } - tor_gettimeofday_cached(&now); + tor_gettimeofday_cached_monotonic(&now); now_ms = (uint32_t)tv_to_msec(&now); /* This algorithm itself assumes that you've got enough memory slack @@ -1832,9 +1832,11 @@ circuits_handle_oom(size_t current_allocation) buf_shrink_freelists(1); /* This is necessary to actually release buffer chunks. */ - log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits.", + log_notice(LD_GENERAL, "Removed "U64_FORMAT" bytes by killing %d circuits; " + "%d circuits remain alive.", U64_PRINTF_ARG(mem_recovered), - n_circuits_killed); + n_circuits_killed, + smartlist_len(circlist) - n_circuits_killed); smartlist_free(circlist); } diff --git a/src/or/relay.c b/src/or/relay.c index dbc1710594..93e1ddd201 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -2151,7 +2151,8 @@ cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue, (void)circ; (void)exitward; (void)use_stats; - tor_gettimeofday_cached(&now); + tor_gettimeofday_cached_monotonic(&now); + copy->inserted_time = (uint32_t)tv_to_msec(&now); cell_queue_append(queue, copy);