Checking for Interrupts

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
knitr::knit_engines$set(callme = callme:::callme_engine)
library(callme)

```{css, echo=FALSE} .callme { background-color: #E3F2FD; } pre.callme span { background-color: #E3F2FD; }

## Introduction

It is considered good practice to allow C code to be interupted if it runs
for an extended period.

`R_CheckUserInterrupt()` checks whether the user is trying to interrupt 
(using `ctrl-c` or similar) and will immediately abort the execution of the code.

## `R_CheckUserInterrupt()` example

In the folowing example, when interrupted, the `Rprintf()` and `return` 
statements will not be executed.  Control will immediately return 
to the user's R session.

```{callme}
#| invisible=TRUE
#include <R.h>
#include <Rinternals.h>
#include <unistd.h>  // for 'sleep()'

SEXP interruptable_sleep(void) {
  while (1) {
    R_CheckUserInterrupt();  // abort if user interrupts. no recovery.
    sleep(1);
  }
  Rprintf("Never get here!  Interrupt causes immediate exit!");
  return R_NilValue;
}
interruptable_sleep()

Continuing C execution after the interrupt

You may also wish to continue execution of the C code after the interrupt (e.g. to tidy and free any resources).

In this example the Rprintf() statment and return will be executed following the interuption.

#| compile=FALSE
#include <R.h>
#include <Rinternals.h>
#include <unistd.h>  // for 'sleep()'
#include <stdbool.h>

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// As suggested by Simon Urbanek
// https://stat.ethz.ch/pipermail/r-devel/2011-April/060702.html
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void check_interrupt_internal(void *dummy) {
  R_CheckUserInterrupt();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// this will call the above in a top-level context so it won't 
// longjmp-out of your context
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool check_interrupt(void) {
  return (R_ToplevelExec(check_interrupt_internal, NULL) == FALSE);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Your code goes here
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SEXP interruptable_sleep2(void) {
  while (1) {
    if (check_interrupt()) break;  // break out of while(). Keep executing
    sleep(1);
  }
  Rprintf("My sleep was interrupted!\n");
  return R_NilValue;
}
interruptable_sleep2()


Try the callme package in your browser

Any scripts or data that you put into this service are public.

callme documentation built on April 4, 2025, 2:37 a.m.