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:
- No Error occurred.
- A error occurred, but it was caught by a
tryCatch
. - 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.
- Whether we are in an interactive R-Session or not.
- Whether the
traceback(x)
value is set tox=NULL
or an integer, in this examplex=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)