Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plan for debugging (and traceback) #253

Open
mllg opened this issue Sep 21, 2018 · 2 comments
Open

Plan for debugging (and traceback) #253

mllg opened this issue Sep 21, 2018 · 2 comments

Comments

@mllg
Copy link

mllg commented Sep 21, 2018

I know there is the "transparent" plan, but I'm still not very helpful tracebacks:

library(future)
plan("transparent")
f = function(x) if (x > 5) stop("whoops") else x
g = function(x) f(x)
result %<-% g(10)
> Error in f(x) : whoops
> traceback()
17: stop(condition)
16: resignalCondition(future)
15: signalEarly(x, ...)
14: resolved.Future(future)
13: NextMethod()
12: resolved.UniprocessFuture(future)
11: resolved(future)
10: signalEarly(future, collect = FALSE)
9: run.UniprocessFuture(future)
8: run(future)
7: sequential(expr, envir = envir, substitute = FALSE, lazy = lazy,
       seed = seed, globals = globals, local = local, earlySignal = earlySig
nal,
       label = label, ...)
6: evaluator(expr, envir = envir, substitute = FALSE, lazy = lazy,
       seed = seed, globals = globals, packages = packages, ...)
5: (function (expr, envir = parent.frame(), substitute = TRUE, globals = TRU
E,
       packages = NULL, lazy = FALSE, seed = NULL, evaluator = plan("next"),

       ...)
   {
       if (substitute)
           expr <- substitute(expr)
       if (!is.function(evaluator)) {
           stop("Argument 'evaluator' must be a function: ", typeof(evaluato
r))
       }
       future <- evaluator(expr, envir = envir, substitute = FALSE,
           lazy = lazy, seed = seed, globals = globals, packages = packages,

           ...)
       if (!inherits(future, "Future")) {
           stop("Argument 'evaluator' specifies a function that does not ret
urn a Future object: ",
               paste(sQuote(class(future)), collapse = ", "))
       }
       future
   })(g(10), envir = <environment>, lazy = FALSE, seed = NULL, globals = TRU
E)
4: do.call(future::future, args = future.args, envir = assign.env)
3: futureAssign(name, expr, envir = envir, assign.env = assign.env,
       substitute = FALSE)
2: futureAssignInternal(target, expr, envir = envir, substitute = FALSE)
1: result %<-% g(10)

-> I just get the top level call, nothing about f().

  1. Would it be possible to create a plan which just calls base R functions? E.g., futureCall calls do.call, futureAssign calls assign, future_lapply calls lapply ...?
  2. Alternatively, would it be possible to store and query the traceback?
  3. Maybe there could also be a plan for the evaluate package?
@HenrikBengtsson
Copy link
Owner

Sorry for the delay. Yes, the idea of the transparent backend is to simplify troubleshooting. It would be nice to have a barebone, minimal-overhead future backend for troubleshooting etc. Things like lazy evaluation (lazy = TRUE) makes this much complicated since we cannot just call eval() on the future expression immediately when the future is created. Having said that, I'll add it to the list of simplifying transparent, which currently just utilizes the sequential backend.

@HenrikBengtsson
Copy link
Owner

This is quite an old issue, but regarding FR 2, there's backtrace();

library(future)
plan(sequential)
f <- function(x) if (x > 5) stop("whoops") else x
g <- function(x) f(x)
result %<-% g(10)

which gives

> result
Error in f(x) : whoops

We can get a clean stack trace by calling backtrace() on this future/promise:

> backtrace(result)
[[1]]
result %<-% g(10)

[[2]]
futureAssignInternal(target, expr, envir = envir, substitute = FALSE)

[[3]]
futureAssign(name, expr, envir = envir, assign.env = assign.env, 
    substitute = FALSE)

[[4]]
do.call(future::future, args = future.args, envir = assign.env)

[[5]]
(function (expr, envir = parent.frame(), substitute = TRUE, lazy = FALSE, 
    seed = FALSE, globals = TRUE, packages = NULL, label = NULL, 
    gc = FALSE, ...) 
{
    if (substitute) 
        expr <- substitute(expr)
    makeFuture <- plan("next")
    future <- makeFuture(expr, substitute = FALSE, envir = envir, 
        lazy = lazy, seed = seed, globals = globals, packages = packages, 
        label = label, gc = gc, ...)
    if (!inherits(future, "Future")) {
        stop(FutureError("plan(\"next\") returned a function that does not return a Future object: ", 
            paste(sQuote(class(future)), collapse = ", ")))
    }
    future
})(g(10), envir = <environment>, lazy = FALSE, seed = NULL, globals = TRUE)

[[6]]
makeFuture(expr, substitute = FALSE, envir = envir, lazy = lazy, 
    seed = seed, globals = globals, packages = packages, label = label, 
    gc = gc, ...)

[[7]]
SequentialFuture(..., envir = envir)

[[8]]
UniprocessFuture(expr = expr, envir = envir, substitute = FALSE, 
    lazy = lazy, globals = globals, local = local, ...)

[[9]]
Future(expr = expr, substitute = FALSE, envir = envir, lazy = lazy, 
    asynchronous = FALSE, local = local, globals = globals, packages = packages, 
    ...)

[[10]]
eval(quote(g(10)), new.env())

[[11]]
g(10)

[[12]]
function(x) f(x)

[[13]]
function(x) if (x > 5) stop("whoops") else x

[[14]]
f(x)

@HenrikBengtsson HenrikBengtsson changed the title Plan for debugging Plan for debugging (and traceback) Nov 7, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants