Skip to content
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

fix: limit the rate of interruption checks #942

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
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
23 changes: 23 additions & 0 deletions src/rinterface_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -2284,6 +2284,29 @@ void checkInterruptFn(void *dummy) {
}

igraph_error_t R_igraph_interrupt_handler(void *data) {
/* Limit how often checks are done. Also limit timing checks. */
static int iter = 0;
if (++iter < 4) return IGRAPH_SUCCESS;
iter = 0;
/* On systems that have fast and high-resolution timing functions,
* we try to limit interruption checks to at most once per 1 millisecond. */
#if defined(__MACH__)
/* On Darwin/macOS, CLOCK_MONOTONIC_RAW_APPROX is the fastest method. */
static uint64_t last = 0;
uint64_t now = clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW_APPROX);
if (now != 0) { /* now == 0 indicates failure */
if (now - last < 1000000) return IGRAPH_SUCCESS;
last = now;
}
#elif defined(__linux__) || defined(__FreeBSD__)
static long last = 0;
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) == 0) {
long now = ts.tv_nsec;
if (now - last < 1000000) return IGRAPH_SUCCESS;
last = now;
}
#endif
/* We need to call R_CheckUserInterrupt() regularly to enable interruptions.
* However, if an interruption is pending, R_CheckUserInterrupt() will
* longjmp back to the top level so we cannot clean up ourselves by calling
Expand Down
Loading