2

I have written some software in R that performs a job every night, triggered by a cron event. Now I want the software to send out a notification based upon the exit status of the software. There are thee possible states the software can be in after it finishes:

  1. No Error occurred.
  2. A error occurred, but it was caught by a tryCatch.
  3. A error occurred and it was not caught, the software terminated unexpectedly.

For me the first two cases are summaries as "no error" and the last one as "error".

Then I have identified two different modes that change the way errorhandling in R works.

  1. Whether we are in an interactive R-Session or not.
  2. Whether the traceback(x) value is set to x=NULL or an integer, in this example x=1.

To test the behavior of R in all these different scenarios I came up with a small MWE and a table to show my results. You'll find the MWE below. In this table you can see that there are several cases (e.g. Non-Interactive and x=1) where you have not enough information to discriminate the three different stages from one another.

How can I reliably determine from the on.exit()-Function how my R-Program terminated?
Or how can I reliably determine from the on.exit()-Function if my R-Program had an error?

interactive traceback(x) test No Error uncaught Error caught Error
TRUE 1 nchar(geterrmessage())==0 TRUE FALSE FALSE
TRUE 1 is.null(.traceback()) FALSE FALSE FALSE
TRUE NULL nchar(geterrmessage())==0 TRUE FALSE FALSE
TRUE NULL is.null(.traceback()) TRUE FALSE TRUE
FALSE 1 nchar(geterrmessage())==0 TRUE FALSE FALSE
FALSE 1 is.null(.traceback()) FALSE FALSE FALSE
FALSE NULL nchar(geterrmessage())==0 TRUE FALSE FALSE
FALSE NULL is.null(.traceback()) TRUE TRUE TRUE
test <- function(error, trace) {
  on.exit(
    {
      print(nchar(geterrmessage()) == 0)
      print(is.null(.traceback(trace)))
    },
    add = TRUE,
    after = TRUE
  )

  if (error == "c") {
    result <- tryCatch({
      "1" + 1
    }, warning = function(w) {
      print(w)
    }, error = function(e) {
      print(e)
    }, finally = {
      print("finally")
    })
  } else if (error == "u") {
    "1" + 1
  } else if (error == "n") {
    1 + 1
  } else {
    print("BAD")
  }
}

.rs.restartR()
options(error = NULL)
test(error = "n", trace=NULL)

.rs.restartR()
options(error = NULL)
test(error = "u", trace=NULL)

.rs.restartR()
options(error = NULL)
test(error = "c", trace=NULL)

#########

.rs.restartR()
options(error = NULL)
test(error = "n", trace=1)

.rs.restartR()
options(error = NULL)
test(error = "u", trace=1)

.rs.restartR()
options(error = NULL)
test(error = "c", trace=1)
Someone2
  • 421
  • 2
  • 15
  • There is no way for any language to report a total crash by itself. However, you should be able to craft a shell script or equivalent; have your R function create a dummy process and then let the shell script check the status of that process; if your function doesn't crash then have it terminate the dummy process on exit. – Carl Witthoft Jan 02 '23 at 13:03
  • On the one hand you're completely right. On the other it is so close to working: When the traceback would work the same way in script-mode and interactively then I could do what I want. To me it still feels as a bug that traceback acts so differently in both modes. – Someone2 Jan 03 '23 at 13:14

0 Answers0