libctdb: test: logging enhancement
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 21 Jun 2010 05:32:05 +0000 (15:02 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 21 Jun 2010 05:32:05 +0000 (15:02 +0930)
Make children log through a pipe to the parent, which then spits it out
only if the child has a problem.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
libctdb/test/failtest.c
libctdb/test/log.c
libctdb/test/log.h
libctdb/test/utils.h

index 2560e3e5ebafa4c6de885a2c17c27a48dfbfb3fe..d42ab057094be07f1167a959c0ea7966c1f853ee 100644 (file)
@@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #include "tui.h"
 #include "log.h"
 #include "failtest.h"
+#include "ctdb-test.h"
 #include "talloc.h"
 #include "dlinklist.h"
 #include <stdlib.h>
@@ -229,8 +230,10 @@ bool should_i_fail_once(const char *location)
 bool should_i_fail(const char *func)
 {
        pid_t child;
-       int status;
+       int status, pfd[2];
        struct fail_decision *dec;
+       size_t log_size;
+       char *log;
 
        if (failpath)
                return do_failpath(func);
@@ -253,6 +256,9 @@ bool should_i_fail(const char *func)
 
        DLIST_ADD_END(decisions, dec, struct fail_decision);
 
+       if (pipe(pfd) != 0)
+               err(1, "pipe failed for failtest!");
+
        fflush(stdout);
        child = fork();
        if (child == -1)
@@ -261,6 +267,10 @@ bool should_i_fail(const char *func)
        /* The child actually fails.  The script will screw up at this
         * point, but should not crash. */
        if (child == 0) {
+               /* Log to parent (including stderr if things go really bad). */
+               close(pfd[0]);
+               dup2(pfd[1], STDOUT_FILENO);
+               dup2(pfd[1], STDERR_FILENO);
                dec->failed = true;
                if (!failtest_no_report || !strstr(func, failtest_no_report))
                        fails++;
@@ -268,6 +278,10 @@ bool should_i_fail(const char *func)
        }
 
        dec->failed = false;
+
+       close(pfd[1]);
+       log = grab_fd(pfd[0], &log_size);
+
        while (waitpid(child, &status, 0) < 0) {
                if (errno != EINTR)
                        err(1, "failtest waitpid failed for child %i",
@@ -276,19 +290,20 @@ bool should_i_fail(const char *func)
 
        /* If child succeeded, or mere script failure, continue. */
        if (WIFEXITED(status) && (WEXITSTATUS(status) == EXIT_SUCCESS
-                                 || WEXITSTATUS(status) == EXIT_SCRIPTFAIL))
+                                 || WEXITSTATUS(status) == EXIT_SCRIPTFAIL)) {
+               talloc_free(log);
                return false;
-
-       /* Report unless child already reported it. */
-       if (!WIFEXITED(status) || WEXITSTATUS(status) != EXIT_SILENT) {
-               /* Reproduce child's path */
-               dec->failed = true;
-               log_line(LOG_ALWAYS, "Child %s %i on failure path: %s",
-                        WIFEXITED(status) ? "exited" : "signalled",
-                        WIFEXITED(status) ? WEXITSTATUS(status)
-                        : WTERMSIG(status), failpath_string());
        }
-       exit(EXIT_SILENT);
+
+       /* Reproduce child's path */
+       dec->failed = true;
+
+       log_line(LOG_ALWAYS, "Child %s %i on failure path: %s",
+                WIFEXITED(status) ? "exited" : "signalled",
+                WIFEXITED(status) ? WEXITSTATUS(status)
+                : WTERMSIG(status), failpath_string());
+       log_line(LOG_ALWAYS, "Child output:\n%s", log);
+       exit(EXIT_FAILURE);
 }
 
 void dump_failinfo(void)
index a4a9be62b859f4e700e16de348711f94d20443aa..c8293be8f6fe7e66d3d8be37db10d60cd3cd7e2e 100644 (file)
@@ -26,6 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #include "expect.h"
 #include <string.h>
 #include <talloc.h>
+#include <err.h>
 
 static struct {
        enum log_type   type;
@@ -37,7 +38,6 @@ static struct {
        { LOG_VERBOSE,  "verbose" },
 };
 
-static FILE *logstream;
 static int typemask = ~LOG_VERBOSE;
 
 bool log_line(enum log_type type, const char *format, ...)
@@ -50,8 +50,10 @@ bool log_line(enum log_type type, const char *format, ...)
        line = talloc_vasprintf(NULL, format, ap);
        va_end(ap);
 
-       if (!type || (type & typemask))
-               fprintf(logstream ?: stderr, "%s\n", line);
+       if (!type || (type & typemask)) {
+               printf("%s\n", line);
+               fflush(stdout);
+       }
 
        ret = expect_log_hook(line);
        talloc_free(line);
@@ -69,8 +71,9 @@ static void log_partial_v(enum log_type type,
 
        /* write to the end of buffer */
        if (vsnprintf(buf + len, bufsize - len - 1, format, ap)
-                       > bufsize - len - 1)
-               log_line(LOG_ALWAYS, "log_line_partial buffer is full!");
+           > bufsize - len - 1) {
+               errx(1, "log_line_partial buffer is full!");
+       }
 
        ptr = buf;
 
@@ -222,7 +225,6 @@ static void log_admin_help(int agc, char **argv)
 
 static void log_init(void)
 {
-       logstream = stdout;
        if (tui_quiet)
                typemask = 0;
        tui_register_command("log", log_admin, log_admin_help);
index d19d6b2f5c04e8f703410cab6430da613df22cab..068dd55543be39184bc62375d18ff130be313b77 100644 (file)
@@ -44,5 +44,4 @@ bool log_line(enum log_type type, const char *format, ...);
 /* Builds up buffer and prints out line at a time. */
 void log_partial(enum log_type type, char *buf, unsigned bufsize,
                 const char *format, ...);
-
 #endif /* __HAVE_LOG_H */
index eb849135895be850241bba158870980927229027..c8ba7cee739872288b97762b4a20d0508aee52dc 100644 (file)
@@ -56,7 +56,6 @@ static inline bool strends(const char *a, const char *b)
 enum exitcodes {
        /* EXIT_SUCCESS, EXIT_FAILURE is in stdlib.h */
        EXIT_SCRIPTFAIL = EXIT_FAILURE + 1,
-       EXIT_SILENT,
 };
 
 /* init code */