Signal handling in R

Recently I have been programming quite a lot in R, and today stumbled over the problem to implement a kind of monitoring loop in R. Typically that would be a infinite loop with sleep calls, but I wanted to allow for waking up from the sleep via sending UNIX style signals, in particular SIGINT. After some searching I found Beyond Exception Handling: Conditions and Restarts from the Advanced R book. But it didn’t really help me a lot to program an interrupt handler.

My requirements were:

  • an interruption of the work-part should be immediately restarted
  • an interruption of the sleep-part should go immediately into the work-part

Unfortunately it seems not to be possible to ignore interrupts at all from with the R code. The best one can do is install interrupt handlers and try to repeat the code which was executed while the interrupt happened. This is what I tried to implement with the following code below. I still have to digest the documentation about conditions and restarts, and play around a lot, but at least this is an initial working version.

workfun <- function() {
  i <- 1
  do_repeat <- FALSE
  while (TRUE) {
    message("begin of the loop")
    withRestarts(
      {
        # do all the work here
        cat("Entering work part i =", i, "\n");
        Sys.sleep(10)
        i <- i + 1
        cat("finished work part\n")
      }, 
      gotSIG = function() { 
        message("interrupted while working, restarting work part")
        do_repeat <<- TRUE
        NULL
      }
    )
    if (do_repeat) {
      cat("restarting work loop\n")
      do_repeat <- FALSE
      next
    } else {
      cat("between work and sleep part\n")
    }
    withRestarts(
      {
        # do the sleep part here
        cat("Entering sleep part i =", i, "\n")
        Sys.sleep(10)
        i <- i + 1
        cat("finished sleep part\n")
      }, 
      gotSIG = function() {
        message("got work to do, waking up!")
        NULL
      }
    )
    message("end of the loop")
  }
}

cat("Current process:", Sys.getpid(), "\n");

withCallingHandlers({
    workfun()
  },
  interrupt = function(e) {
    invokeRestart("gotSIG")
  })

While not perfect, I guess I have to live with this method for now.

1 Response

Leave a Reply

Your email address will not be published. Required fields are marked *