Search code examples
rrcppabort

Check for abort


I used to depend on the package RcppProgress to check for user abortion inside a long loop with Progress::check_abort(). But I just received an email from the CRAN team to tell me (and to other maintainers) that RcppProgress has bugs and will be removed soon in absence of maintainer (actually it seems already removed). Is there another way to check for abortion?

I found that R_CheckUserInterrupt exists. How to change my code to use this function? In Writing R extensions the function returns void so I do not understand how it works. It seems to exit immediately.

Rcpp::checkUserInterrupt seems to present the same behavior. And R: How to write interruptible C++ function, and recover partial results presents a kind of hack not recomented by its author. I would like to exit the loop correctly cleaning object allocated on the heap and returning partial output

// [[Rcpp::depends(RcppProgress)]]
#include <progress.hpp>
#include <Rcpp.h>

// [[Rcpp::export]]
SEXP f()
{
  for( int i = 0 ; i < 100000 ; i++)
  {
    if (Progress::check_abort())
    {
       delete some_var;
       return partial_output;
    }
    else
      //do_stuff();
  }
}

Solution

  • After reading the sources of Rcpp I found that Rcpp::checkUserInterrupt() throw an internal::InterruptedException. This works:

    for (long i = 0 ; i < 100000000 ; i++)
    {
        try 
        {
          Rcpp::checkUserInterrupt();
        }
        catch(Rcpp::internal::InterruptedException e) 
        {
          delete some_var;
          return partial_output;
        }
     }
    

    It is slow but exactly like Process::check_abort. Optionally, as advised in Rcpp Attributes, one can check only every 100 or 1000 iteration to speed up the code.

    for (long i = 0 ; i < 100000000 ; i++)
    {
      if (i % 100 == 0)
      {
         try 
         {
           Rcpp::checkUserInterrupt();
         }
         catch(Rcpp::internal::InterruptedException e) 
         {
           delete some_var;
           return partial_output;
         }
       }
     }