Skip to content

Commit 8fb2f4a

Browse files
committed
Run r_safe_eval() in top-level-exec context
1 parent 48301da commit 8fb2f4a

File tree

2 files changed

+11
-5
lines changed

2 files changed

+11
-5
lines changed

crates/harp/src/exec.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,11 @@ impl RFunction {
9191
}
9292

9393
pub fn r_safe_eval(expr: RObject, env: RObject) -> crate::Result<RObject> {
94-
unsafe {
94+
// We could detect and cancel early exits from the r side, but we'd be at
95+
// risk of very unlucky interrupts occurring between `rf_eval()` and our
96+
// `on.exit()` handling. So stay on the safe side by wrapping in
97+
// top-level-exec. This also insulates us from user handlers.
98+
r_top_level_exec(|| unsafe {
9599
let eval_call = RCall::new(r_symbol!("safe_evalq"))
96100
.add(expr.sexp)
97101
.add(env)
@@ -120,8 +124,8 @@ pub fn r_safe_eval(expr: RObject, env: RObject) -> crate::Result<RObject> {
120124
});
121125
}
122126

123-
return Ok(RObject::new(out));
124-
}
127+
Ok(RObject::new(out))
128+
})?
125129
}
126130

127131
impl From<&str> for RFunction {

crates/harp/src/modules/init.R

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
# - Error slot: Character vector of length 2 [message, trace], with `trace`
66
# possibly an empty string.
77
#
8-
# TODO: Prevent this function from jumping with on.exit
8+
# We could detect and cancel early exits from here but we'd be at risk of very
9+
# unlucky interrupts occurring between `Rf_eval()` and our `on.exit()`
10+
# handling. So it's up to the caller to deal with early exits, for instance with
11+
# a top-level-exec context.
912
safe_evalq <- function(expr, env) {
1013
# Create a promise to make call stack leaner
1114
do.call(delayedAssign, list("out", substitute(expr), env))
@@ -38,7 +41,6 @@ safe_evalq <- function(expr, env) {
3841

3942
withCallingHandlers(
4043
list(out, NULL),
41-
interrupt = handler,
4244
error = handler
4345
)
4446
}

0 commit comments

Comments
 (0)