1

Say, I have written a compressor function of the form:

compress <- function(text, file){
    c <- paste0("gzip -c > ",shQuote(file))
    p <- pipe(c, open = "wb")
    on.exit(close(p))
    writeLines(text, p)
}

Now I can compress strings like this:

compress("Hello World", "test.gz")
system("zcat test.gz")
## Hello World

However, how can I check that the programm gzip called by pipe() succeeds?

E.g.

compress("Hello World", "nonexistent-dir/test.gz")
## sh: nonexistent-dir/test.gz: No such file or directory

results in an error message printed on STDERR but I have no way in creating an R error. The program just continues without saving my text.

I know that I can just check for the existence of the target file in this example. But there are many possible errors, like end of disk space, the program was not found, some library is missing, the program was found but the ELF interpreter was not etc. I just can't think of any way to test for all possible errors.

I searched the help page ?pipe, but could find no hint.

As a UNIX-specific approach, I tried to trap the SIGPIPE signal, but could not find a way to do this. Stack Overflow questions regarding this topic remain unanswered as of now [1] [2]

How do I check the exit code or premature termination of a program called with pipe()?

akraf
  • 2,965
  • 20
  • 44

1 Answers1

0

I have not found a solution using pipe(), but the package processx has a solution. I first create the external process as a background process, obtain a connection to it and write to that connection.

Before I start to write, I check if the process is running. After all is written, I can check the exit code of the program.

library(processx)
p <- process$new("pigz","-c",stdin="|", stdout = "/tmp/test.gz")
if(!p$is_alive()) stop("Subprocess ended prematurely")
con <- p$get_input_connection()
# Write output
conn_write(con, "Hello World")
close(con)
p$wait()
if(p$get_exit_status() != 0) stop("Subprocess failed")
system("zcat /tmp/test.gz")
akraf
  • 2,965
  • 20
  • 44