Skip to content

Commit ec6c05c

Browse files
committed
fix: limit the rate of interruption checks
1 parent e2fd870 commit ec6c05c

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

src/rinterface_extra.c

+23
Original file line numberDiff line numberDiff line change
@@ -2348,6 +2348,29 @@ void checkInterruptFn(void *dummy) {
23482348
}
23492349

23502350
int R_igraph_interrupt_handler(void *data) {
2351+
/* Limit how often checks are done. Also limit timing checks. */
2352+
static int iter = 0;
2353+
if (++iter < 4) return IGRAPH_SUCCESS;
2354+
iter = 0;
2355+
/* On systems that have fast and high-resolution timing functions,
2356+
* we try to limit interruption checks to at most once per 1 millisecond. */
2357+
#if defined(__MACH__)
2358+
/* On Darwin/macOS, CLOCK_MONOTONIC_RAW_APPROX is the fastest method. */
2359+
static uint64_t last = 0;
2360+
uint64_t now = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW_APPROX);
2361+
if (now != 0) { /* now == 0 indicates failure */
2362+
if (now - last < 1000000) return IGRAPH_SUCCESS;
2363+
last = now;
2364+
}
2365+
#elif defined(__linux__) || defined(__FreeBSD__)
2366+
static long last = 0;
2367+
struct timespec ts;
2368+
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
2369+
long now = ts.tv_nsec;
2370+
if (now - last < 1000000) return IGRAPH_SUCCESS;
2371+
last = now;
2372+
}
2373+
#endif
23512374
/* We need to call R_CheckUserInterrupt() regularly to enable interruptions.
23522375
* However, if an interruption is pending, R_CheckUserInterrupt() will
23532376
* longjmp back to the top level so we cannot clean up ourselves by calling

0 commit comments

Comments
 (0)