Using future_promise
with catch(.)
(or then(onRejected=)
), the error is still marked as "Unhandled" even though I think I'm attempting to handle it.
library(future)
library(promises)
plan(multicore, workers = 3)
Sys.getpid()
# [1] 1270066
nbrOfFreeWorkers()
# [1] 3
thisproc <- promises::future_promise({
setTimeLimit(elapsed = 2, transient = TRUE)
Sys.sleep(3)
1L
}, seed = TRUE) %>%
promises::then(
function(val) {
message("survived: ", val)
val
}) %>%
catch(
function(error) {
message("terminated: ", substring(conditionMessage(error), 1, 16))
NULL
})
# terminated: Unexpected resul
# Unhandled promise error: Unexpected result (of class ‘NULL’ != ‘FutureResult’) retrieved for MulticoreFuture future (label = ‘<none>’, expression = ‘{; setTimeLimit(elapsed = 2, transient \
# = TRUE); Sys.sleep(3); 1L; }’):
once that returned, then
nbrOfFreeWorkers()
# [1] 2
resetWorkers(plan())
# NULL
nbrOfFreeWorkers()
# [1] 3
(I used substring
just to differentiate an error-like string messaged by my function, and the full condition message being cat
ted to the console.)
- It reports "Unhandled" despite the code handling it (the
terminated:
is printed); - It reports it twice;
and most importantly,
- The worker is not freed until I explicitly free it, despite the
then
-chain functioning.
According to the source, it appears that rejectionHandled
is only referenced/set in this one file, and it should be setting the flag:
doRejectFinalReason = function(reason) {
private$value <- reason
private$state <- "rejected"
later::later(function() {
lapply(private$onRejected, function(f) {
private$rejectionHandled <- TRUE
f(private$value)
})
private$onRejected <- list()
later::later(~{
if (!private$rejectionHandled) {
# warning() was unreliable here
cat(file=stderr(), "Unhandled promise error: ", reason$message, "\n", sep = "")
}
})
})
}
I assumed that since f(private$value)
is called (as evidenced by the "terminated:"
message I inserted), then the private_rejectionHandled
should already have been updated. There are no other errors in this pipe, so it should not have reset the rejectionHandled
flag.
Incidentally, I tried (without success) to call later::run_now()
throughout the process to make sure that all promises are being run, though I was only stabbing in the dark (and it did not change the result).
Also, I can find attributes(thisproc)$promise_impl$.__enclos_env__$private$rejectionHandled
, see it is FALSE
, and change it to TRUE
, but we still see the "Unhandled" console output, indicating something else is at work here. https://github.com/rstudio/promises/issues/86#issuecomment-1252420305 is related (or perhaps the same thing).
Linux, R-4.2.2, future-1.30.0 (1.31.0 is released), promises-1.2.0.1, later-1.3.0.