Closed dselivanov closed 2 years ago
I don't think R actually allows any of the above. The problem is that the C-level interface is very limited when it comes to error handling and it doesn't support condition objects. The error comes directly from R_curErrorBuf()
so Rserve is just a pass-through from R. I'll see if I can dig out more or if we could add more support in R.
@s-u do you think there is a chance to get such improvement in R 4.1? Should I create a ticket on R-bugzilla?
Ok, I have been digging through the whole mess of condition handling in R and I think I have at least a work-around for catching the conditions. Essentially it involves installing a calling handler for the "error"
condition which stashes the condition, but then continues to the default handler to trigger the error so we get the traceback.
error_with_condition = function(object = NULL) {
cond = errorCondition("this is an error with condition",
object = object,
class = "CustomError")
stop(cond)
}
caught_rserve_eval = Rserve::Rserve.eval(quote(error_with_condition("hello")), last.value = TRUE)
# Error: this is an error with condition
str(caught_rserve_eval)
# Class 'Rserve-eval-error' hidden list of 5
# $ error : chr "Error: this is an error with condition\n"
# $ traceback :Dotted pair list of 2
# ..$ : chr "stop(cond)"
# ..$ : chr "error_with_condition(\"hello\")"
# $ expression: int NA
# $ context : NULL
# $ condition :List of 3
# ..$ message: chr "this is an error with condition"
# ..$ call : NULL
# ..$ object : chr "hello"
# ..- attr(*, "class")= chr [1:3] "CustomError" "error" "condition"
The mechanism is fairly generic, so it would be possible to allow injection of arbitrary handlers, so I am reserving the right to change the API for the handler
argument - it could be a list just like in tryCatch
, but for now only one handler is added so if that sounds like a good idea that may be useful, please feel free to file a feature request.
Never mind the last comment - I have now changed the API in 57d1c80 such that handlers
is a named list of handlers, so arbitrary calling handlers can be registered with the default being handlers = list(error = .save.condition)
which saves the condition for retrieval upon return from Rserve.eval
.
Hi Simon,
I'm trying to figure out how to use
Rserve.eval
to safely evaluate expression and get stack trace in case of fail. I face couple of challenges:Rserve.eval
(such as"Error: this is an error with condition"
in example below). I can sink all the stderr stream to/dev/null
beforeRserve.eval
call, but then all the messages produced by evaluated expression will also go to/dev/null
...Consider following example: