Skip to content

Commit cd09ca4

Browse files
committed
src: clamp idle time to avoid underflow in metrics
Clamp idle time values before subtracting from loop duration to avoid unsigned underflow when clock skew causes idle time to be slightly larger than total loop time. This manifests on Windows when the loop is nearly 100% idle. Applied in two locations: - uv_metrics_cb_: prevents bogus rolling_est_lag_ values - get_event_loop_stats_: prevents bogus loop_utilization values Fixes: nodesource/nsolid-private#15 PR-URL: #372 Reviewed-By: Juan José Arboleda <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]>
1 parent 45abe09 commit cd09ca4

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

src/nsolid/nsolid_api.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,6 +611,10 @@ void EnvInst::uv_metrics_cb_(nsuv::ns_prepare* handle, EnvInst* envinst) {
611611
// Use the previous values to calculate the values for this loop iteration.
612612
loop_duration = metrics_cb_time - envinst->prev_metrics_cb_time_;
613613
loop_idle_time = idle_time - envinst->prev_loop_idle_time_;
614+
// Clamp loop_idle_time to avoid unsigned underflow in loop_proc_time when
615+
// clock skew causes idle_time to be slightly larger than loop_duration.
616+
if (loop_idle_time > loop_duration)
617+
loop_idle_time = loop_duration;
614618
loop_proc_time = loop_duration - loop_idle_time;
615619
events_procd = metrics->events - envinst->prev_events_processed_;
616620
events_waiting = metrics->events_waiting - envinst->prev_events_waiting_;
@@ -2162,6 +2166,12 @@ void EnvInst::get_event_loop_stats_(EnvInst* envinst,
21622166
uint64_t loop_idle_time = uv_metrics_idle_time(envinst->event_loop());
21632167
uint64_t loop_diff = stor->current_hrtime_ - stor->prev_call_time_;
21642168
uint64_t idle_diff = loop_idle_time - stor->prev_idle_time_;
2169+
// On some platforms the clocks backing loop_diff and idle_diff can differ by
2170+
// a few hundred nanoseconds when the loop is nearly 100% idle, making
2171+
// idle_diff slightly larger than loop_diff. Clamp to avoid unsigned
2172+
// underflow in proc_diff and bogus utilization values.
2173+
if (idle_diff > loop_diff)
2174+
idle_diff = loop_diff;
21652175
uint64_t proc_diff = loop_diff - idle_diff;
21662176
uint64_t count_diff = metrics->loop_count - stor->loop_iterations;
21672177
auto entry_exit = envinst->provider_times();

0 commit comments

Comments
 (0)