Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use tryCatch with withTimeout to timeout Rcpp function without stopping execution of script

Tags:

r

try-catch

rcpp

I want to place a time limit on a function that I'm calling, so that if it times out then it just moves onto the next part of the script (which I am running by source("...")). The function is written using Rcpp and has checkUserInterrupt(); included frequently throughout. I have been using withTimeout in the R.utils package with the option onTimeout = silent, but timing out is still pausing execution of the script.

I then ran this within tryCatch to return NULL in the case of any errors, but it is still stopping my script. I have included a short function that replicates this issue.

#include <Rcpp.h>
#include <chrono>
#include <thread>

using namespace Rcpp;

void sleep_fn(int n) // sleeps for n seconds
{
  std::chrono::seconds dura( n );
  std::this_thread::sleep_for( dura );
}

// [[Rcpp::export]]
int sleep_for(int n) // sleeps for n seconds and then returns n
{
  for (int i = 0; i < n; i++)
  {
    checkUserInterrupt();
    sleep_fn(1);
  }
  return(n);
}

Now, for comparison, let's run this as well as the R command Sys.sleep(). See that this is working as it's supposed to, but for sleep_for it's still throwing an exception which stops my script.

> tryCatch(withTimeout(Sys.sleep(10), timeout = 5), error = function(ex) return(NULL))
NULL

> tryCatch(withTimeout(sleep_for(10), timeout = 5), error = function(ex) return(NULL))
Error in .Call(<pointer: 0x108cc17b0>, n) : reached elapsed time limit

> tryCatch(withTimeout(sleep_for(10), timeout = 5, onTimeout = "silent"), error = function(ex) return(NULL))
Error in .Call(<pointer: 0x108cc17b0>, n) : reached elapsed time limit

Why isn't tryCatch doing what I think it should? And is there anything I can do in order to get it to work?

(I'm using R version 4.0.3, Rcpp version 1.0.6, R.utils version 2.10.1) Edit: and am on MacOS 11.3.1

like image 251
bgs Avatar asked May 21 '21 11:05

bgs


1 Answers

Try this template and see if it works. I have used it and it exists silently.

# Timeout is in seconds
# https://www.rdocumentation.org/packages/R.utils/versions/2.7.0/topics/withTimeout
tryCatch(
  {
    withTimeout(some_function(), timeout = 60)                    
  }
  ,TimeoutException = function(ex) {
    print("Timeout of 60 seconds reached. Function will not be completely run.")
  }
)
like image 193
Nikhil Gupta Avatar answered Nov 13 '22 09:11

Nikhil Gupta