Skip to content

Reprex when it makes R crash #312

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

Closed
llrs opened this issue Feb 6, 2020 · 8 comments
Closed

Reprex when it makes R crash #312

llrs opened this issue Feb 6, 2020 · 8 comments

Comments

@llrs
Copy link

llrs commented Feb 6, 2020

I have some trouble generating the reprex of a process that ends up killing the R process. It makes Rstudio crash and hang up the bare R session (with core dumps).

reprex::reprex({
     # install.packages("BiocManager")
     # BiocManager::install(c("affy", "affydata"))
     library("affy")
     library("affydata")
     data(Dilution)
     Dilution
     eset <- rma(Dilution)
     
     Dilution0 <- Dilution[-c(1:4), ]
     eset <- rma(Dilution0)
})

The error I see is

Rendering reprex...
 
Error: <callr_status_error in get_result(output = out, options):
 callr subprocess failed: could not start R, exited with non-zero status, has crashed or was killed>

See `.Last.error.trace` for a stack trace.

.Last.error.trace:

 Stack trace:

 1. reprex::reprex({ ...
 2. reprex:::reprex_render(r_file, std_file)
 3. callr::r_safe(function(input) { ...
 4. callr:::get_result(output = out, options)
 5. throw(new_callr_error(output, killmsg))

 x callr subprocess failed: could not start R, exited with non-zero status, has crashed or was killed 

Warning message:
partial match of 'topenv' to 'topenvs' 

I don't know if this could be handled different on the reprex side or on the callr side. I originally wrote the issue on callr r-lib/callr#143 but it seems it belongs here. There are some possible workarounds apparently.

I expected to get at least the same message that I see on the R session without RStudio.

@gaborcsardi gaborcsardi changed the title Reprex when it makes callr crass Reprex when it makes R crash Feb 6, 2020
@matthewdwood82
Copy link

Has there been a solution to this bug report? I am experiencing a similar issue. Am running R 4.0.3, and recently uninstall/reinstalled reprex to the latest version.

@llrs
Copy link
Author

llrs commented Oct 28, 2020

Not that I'm aware of

@matthewdwood82
Copy link

That's too bad. Thanks for the note!

@jennybc
Copy link
Member

jennybc commented Dec 29, 2020

I am looking into this for an upcoming reprex release.

jennybc added a commit that referenced this issue Jan 1, 2021
jennybc added a commit that referenced this issue Jan 1, 2021
@jennybc
Copy link
Member

jennybc commented Jan 1, 2021

Notes from addressing this, because I had to settle for a compromise and I learned a few things I don't want to re-learn.


The ideal output would probably consist of:

  • The user's reprex code, processed, BUT with this injected at the top:

    knitr::opts_hooks$set(eval = function(options) {
      options$eval <- FALSE
      options
      })

    which renders as if eval = FALSE for all code, i.e. no code gets evaluated.

  • The usual standard output and error injection, which contains info about the crash and a traceback.

I had to settle for just the latter. Given the current design, it would be very fiddly to get the ideal output and I don't think it's worth it.


I learned about callr:::crash() in r-lib/callr#143.


I did some manual tests with real crashes found by searching for segfault user:tidyverse user:r-lib and crash user:tidyverse user:r-lib and looking for open issues with a good reprex. What reprex() now does seems reasonable, definitely an improvement.


Some segfaults are caught in a way that does not lead to a crash and reprex doesn't work well for these, before or after this issue and PR. It seems to possibly be a rmarkdown::render() or knitr::knit() problem, in that those functions don't work for such code, but also don't error and just return NULL. I don't feel good about trying to detect this edge case from reprex.

A real example where I encountered this is tidyverse/dplyr#5667.

Here's what I see in the R console for this, i.e. the R session survives:

> f3 <- function(...) {
+   withr::defer(2)
+   integer(1) 
+   message('reaching this')
+   data <- dplyr::slice(mtcars, integer(1))
+ }
> f3()
reaching this
Error: segfault from C stack overflow
> 

And here's what happens when I reprex() that code (because md_file is NULL):

> reprex(std_out_err = TRUE)
Rendering reprex...
Error in basename(input) : a character vector argument expected
Run `rlang::last_error()` to see where the error occurred.

> le
<error/rlang_error>
Error in basename(input) : a character vector argument expected
Backtrace:
 1. reprex::reprex(std_out_err = TRUE)
 2. reprex::reprex_impl(...) R/reprex.R:274:2
 3. reprex::reprex_render_impl(r_file, new_session = new_session) R/reprex_impl.R:76:2
 4. reprex::preview(md_file) R/reprex_render.R:163:4
 5. rmarkdown::render(...) R/reprex_render.R:177:2
 7. base::basename(input)
Run `rlang::last_trace()` to see the full context.

In this case, the std_out_err file does contain useful info (Error: segfault from C stack overflow), but we don't know to present that to the user, because we didn't get an obvious error from rendering the reprex, we just got NULL.

@jennybc jennybc closed this as completed in 4dc486e Jan 2, 2021
@llrs
Copy link
Author

llrs commented Jan 2, 2021

Happy new year! Many thanks for looking into this. Will try the dev version, but not sure I understand your last code block. Looking at the linked commit it seems that this is not the behaviour of the development version of reprex. Where does the le object come from?

@jennybc
Copy link
Member

jennybc commented Jan 2, 2021

le is just an alias I set up in my .Rprofile for calling rlang::last_error().

You will also not see the crash info or backtrace if you are on Windows, due to how R behaves and crashes on Windows. See r-lib/callr#178 for more.

@llrs
Copy link
Author

llrs commented Jan 2, 2021

Oh. Great many thanks!

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

3 participants