Process hangs when using pipes with `stdout`, `stderr` for `latexmk -pdf` compilation
jemus42 opened this issue · 2 comments
I am attempting to orchestrate and keep track of dozens of latexmk
compilation processes, and noticed that these processes never finish if I attempt to capture stdout
or stderr
with pipes.
It works when I log to temp files and read the contents back though, and I don't understand what's going on there.
Consider this minimal test.tex
file:
\documentclass{article}
\begin{document}
Hello
\end{document}
Setting stdout
and stderr
to temp files
Works (mostly) as intended:
stdout_file <- tempfile()
stderr_file <- tempfile()
# Cleanup for next run
pc <- processx::process$new(command = "latexmk", args = c("-C"))
pc$wait()
if (file.exists("test.pdf")) file.remove("test.pdf")
p <- processx::process$new(
command = "latexmk", args = c("-pdf", "test.tex"),
stderr = stdout_file,
stdout = stderr_file,
echo_cmd = TRUE
)
p$wait()
p$get_exit_status()
Unfortunately all the output appears to be in stderr
, but that's just a latexmk
thing I assume
readLines(stdout_file)
character(0)
readLines(stderr_file)
[1] "Rc files read:"
[2] " NONE"
[truncated for brevity]
[30] "Latexmk: Log file says output to 'test.pdf'"
[31] "Latexmk: All targets () are up-to-date"
[32] ""
Setting stdout
and stderr
to pipes
Causes the process to hang indefinitely:
# Cleanup for next run
pc <- processx::process$new(command = "latexmk", args = c("-C"))
pc$wait()
if (file.exists("test.pdf")) file.remove("test.pdf")
p <- processx::process$new(
command = "latexmk", args = c("-pdf", "test.tex"),
stderr = "|",
stdout = "|",
echo_cmd = TRUE
)
# Hangs seemingly forever
p$wait()
Setting stdout
and stderr
to pipes with latexmk -C
It's specifically this compilation that's the issue, because piping with e.g. latexmk -C
works fine:
p <- processx::process$new(
command = "latexmk", args = c("-C"),
stderr = "|",
stdout = "|",
echo_cmd = TRUE
)
p$wait()
p$read_all_output_lines()
[1] "Rc files read:"
[2] " NONE"
[3] "Latexmk: This is Latexmk, John Collins, 4 Apr. 2023. Version 4.80."
[4] "No specific requests made, so using default for latexmk."
[5] "Latexmk: Doing main (small) clean up for 'test.tex'"
[6] ""
p$read_all_error_lines()
character(0)
Session Info
Session Info
system("latexmk --version")
#> Latexmk, John Collins, 4 Apr. 2023. Version 4.80
sessioninfo::session_info("processx")
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.3.1 (2023-06-16)
#> os macOS Ventura 13.5.1
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz Europe/Berlin
#> date 2023-09-01
#> pandoc 3.1.1 @ /System/Volumes/Data/Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> processx 3.8.2 2023-06-30 [1] CRAN (R 4.3.0)
#> ps 1.7.5 2023-04-18 [1] CRAN (R 4.3.0)
#> R6 2.5.1 2021-08-19 [1] CRAN (R 4.3.0)
#>
#> [1] /Users/Lukas/Library/R/arm64/4.3/library
#> [2] /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/library
#>
#> ──────────────────────────────────────────────────────────────────────────────
Pipes have buffers, and if you don't read them out, then the process writing to them will indeed stop: https://github.com/r-lib/processx#standard-output-and-error
Always make sure that you read out the standard output and/or error of the pipes, otherwise the background process will stop running!
If you don't need to do anything until the process finishes, then processx::run()
is the easiest to use.
If you want to parse the output while the process is running, then process$new()
is best, here is an example: https://www.tidyverse.org/blog/2018/09/processx-3.2.0/#use-case-wait-for-an-external-process-to-be-ready