callr icon indicating copy to clipboard operation
callr copied to clipboard

`r_bg()` don't finished until run `rp$read_error()` and `rp$read_output()`

Open Ann-Holmes opened this issue 1 year ago • 3 comments

Hello,

Thanks for your great work on callr. It provides a easy way to run self-contained function in a new process.

However, I met some issue when I am using r_bg() in a shiny app. In my shiny app, I use r_bg() to run rmarkdown::render() function. Here is the psudo-code:

render_pdf_rp <- reactive({
  gene_name <- selected_gene()
  log_info(str_glue("Rendering the PDF report for {gene_name}"))
  callr::r_bg(
    function(gene_name, template_file, output_dir) {
      rmarkdown::render(
        input = template_file,
        output_file = stringr::str_glue("Report_{gene_name}.pdf"),
        output_dir = output_dir,
        params = list(gene = gene_name)
      )
      return(file.path(output_dir, stringr::str_glue("Report_{gene_name}.pdf")))
    },
    args = list(
      gene_name = gene_name,
      template_file = rmarkdownPDFTemplatePath),
      output_dir = rmarkdownPDFResultsDir)
    )
  )
})

observe({
  invalidateLater(5000, session)
  if (!render_pdf_rp_done()) {
    log_info("PDF report is not ready yet. Checking the status ...")
    if (!render_pdf_rp()$is_alive() && render_pdf_rp()$get_exit_status() == 0) {
      render_pdf_rp_done(TRUE)
      output_file <- render_pdf_rp()$get_result()
      log_info(str_glue("The PDF report for {selected_gene()} has been generated"))
      log_info(str_glue("PDF report output file: {output_file}"))
      shinyjs::enable("download_pdf")
      shinyjs::hide("pdf_report_loading")
      shinyjs::show("pdf_report_ready")
    } else {
      cat(render_pdf_rp()$read_output())
      cat(render_pdf_rp()$read_error())
    }
  } else {
    log_info("PDF report is ready")
  }
})

output$download_pdf <- downloadHandler(
  filename = function() {
    str_glue("Report_{selected_gene()}.pdf")
  },
  content = function(file) {
    log_info(str_glue("Downloading the PDF report for {selected_gene()}"))
    file.copy(render_pdf_rp()$get_result(), file)
  }
)

I found that render_pdf_rp()$is_alive() is TRUE even if the rmarkdown::render() is finished, unless I call render_pdf_rp()$read_error() and render_pdf_rp()$read_output().

Of course, I can call rend_error() and read_output() each time. But I think it's not straightforward and I don't find any documents related to this issue(If I miss, please tell me, thanks!).

I am not sure this is a bug or a feature. It's better if you can explain it.

Thanks again.

Ann-Holmes avatar Jul 22 '24 07:07 Ann-Holmes

I'm having a similar issue:

I'm calling r_bg() followed by $is_alive() and $wait()

However, $wait() seems to return while the task hasn't finished which leads to errors downstream.

neovom avatar Oct 14 '24 09:10 neovom

@neovom I suspect that your subprocess finished and it is a zombie. But it hard to say without a reproducible example.

gaborcsardi avatar Oct 14 '24 09:10 gaborcsardi

I'll try to make one and raise a separate issue

neovom avatar Oct 14 '24 09:10 neovom