Further to this libarchive_test failure due to SIGPIPE.

The SIGPIPE signal occurs during the call to write() of the following
code in libarchive/archive_read_support_compression_program.c, line 331ff:

               do {
                        ret = write(state->child_stdin, p, avail);
                } while (ret == -1 && errno == EINTR);

                if (ret > 0) {
                        /* Consume whatever we managed to write. */
                        __archive_read_filter_consume(self->upstream, ret);
                } else if (ret == -1 && errno == EAGAIN) {
                        /* Block until child has some I/O ready. */
                        __archive_check_child(state->child_stdin,
                            state->child_stdout);
                } else {
                        /* Write failed. */
                        close(state->child_stdin);
                        state->child_stdin = -1;
                        fcntl(state->child_stdout, F_SETFL, 0);
                        /* If it was a bad error, we're done; otherwise
                         * it was EPIPE or EOF, and we can still read
                         * from the child. */
                        if (ret == -1 && errno != EPIPE)
                                return (-1);
                }

It is clear from the code that an EPIPE error return from the write() is
considered a recoverable situation.

But the man file for write(2) states that a broken pipe will generate
the SIGPIPE signal whose default disposition is to terminate the
program, thus EPIPE cannot be returned from a call to write() unless the
default disposition of the SIGPIPE signal is changed.

The libarchive_test does not change the default disposition of the
SIGPIPE signal thus if the pipe breaks then the test suite will be
terminated without the opportunity for the EPIPE error condition to be
gracefully handled.

I attach a patch that changes the default disposition of SIGPIPE to be
ignored in libarchive_test.  The test suite then runs successfully to
completion with all tests passing.

Cheers
Michael

diff -ur libarchive-2.8.5-orig/libarchive/test/main.c libarchive-2.8.5/libarchive/test/main.c
--- libarchive-2.8.5-orig/libarchive/test/main.c	2010-06-29 12:06:59.000000000 +1200
+++ libarchive-2.8.5/libarchive/test/main.c	2011-11-04 20:36:13.000000000 +1300
@@ -28,6 +28,7 @@
 #include <locale.h>
 #include <stdarg.h>
 #include <time.h>
+#include <signal.h>
 
 /*
  * This same file is used pretty much verbatim for all test harnesses.
@@ -1873,6 +1874,7 @@
 	const char *tmp, *option_arg, *p;
 	char tmpdir[256];
 	char tmpdir_timestamp[256];
+	struct sigaction sa;
 
 	(void)argc; /* UNUSED */
 
@@ -2002,6 +2004,14 @@
 #endif
 
 	/*
+	 * Ignore SIGPIPE signals
+	 */
+	sa.sa_handler = SIG_IGN;
+	sigemptyset(&sa.sa_mask);
+	sa.sa_flags = 0;
+	sigaction(SIGPIPE, &sa, NULL);
+
+	/*
 	 * Create a temp directory for the following tests.
 	 * Include the time the tests started as part of the name,
 	 * to make it easier to track the results of multiple tests.

Reply via email to