noob
noob

Reputation: 119

tar command stuck while generating tar file from java process

Running below command using Runtime exec() method to generate tar of a directory using java

tar -zcvf dest.tar.gz -C dirTotar .

Java code for tar creation

    String command = "tar -zcvf dest.tar.gz -C dirTotar .";
    Process process = Runtime.getRuntime().exec(command);
    process.waitFor()
    return process.exitValue();

Java process is a server which creates tar file after processing after each input. After processing for few input, process is stuck at tar step.

Ran strace -p to find if process is stuck and it shows below output

strace -p 6782 
Process 6782 attached - interrupt to quit 
write(1, "./file"..., 66

I ran the tar command manually for the input directory and it works perfectly. Any pointers why this is happening?

Update:

For directory structure like below

/tmp/dir1
/tmp/dir2
/tmp/dir3
.
.

Directory for which tar is being generated by process is dir1. There are other process which are generating tar for dir2, dir3...

When process generating tar for dir1 is stuck one of the other process trying to tar other directory (dir2, dir3) is also stuck. Can this be cause of issue?

Upvotes: 4

Views: 3190

Answers (1)

dave_thompson_085
dave_thompson_085

Reputation: 38821

Fact 1: tar zcv... outputs for each file it archives a line containing the filename of that file. GNU tar, which you are apparently using, outputs the list to stdout when you specify f with an output file, although it uses stderr when f is specified or defaulted to - (which uses stdout for the archive). The length of each line in the list depends on each filename, and the total length of this list depends on the number of files and the total length of their filenames.

Fact 2: a process run by Java Runtime.exec has its stdout directed to a pipe whose other end is provided to the Java program, so the Java code can read the output from the process. The same is true for stderr, and the reverse for stdin, but they aren't relevant in this case. Your code doesn't read this pipe (or make any use of any of the pipes).

Fact 3: when a process (such as tar) writes to a pipe and nothing reads from (the other end of) that pipe, when the pipe buffer fills the writing process hangs. Your strace shows tar is (apparently hanging) in a write to fd 1 which is stdout. The size of the pipe buffer can vary depending on your system and sometimes other factors, but is usually a few K bytes, which depending on the names of the files you want to archive might be anywhere from tens to hundreds of filenames.

Solution: either change your code to read the output from tar -- see Process.getInputStream() -- or change the command (by removing v) so it doesn't produce (non-error) output.

PS: As noted in the javadoc, ProcessBuilder is preferred since Java 5. By default it also uses pipes from and to the new process, but has (several) methods to change this since Java 7.

Upvotes: 4

Related Questions