Add a new flag, --child-silent-after-fork=no|yes [no].  When enabled,
causes child processes after fork to fall completely silent, which can
make the output a lot less confusing.  In addition it is pretty much
essential in XML output mode, so as to avoid mixing up any child XML
output with the parent's.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@7177 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_libcprint.c b/coregrind/m_libcprint.c
index a5129ef..5ba8bb1 100644
--- a/coregrind/m_libcprint.c
+++ b/coregrind/m_libcprint.c
@@ -53,7 +53,12 @@
 static void send_bytes_to_logging_sink ( Char* msg, Int nbytes )
 {
    if (!VG_(logging_to_socket)) {
-      VG_(write)( VG_(clo_log_fd), msg, nbytes );
+      /* VG_(clo_log_fd) could have been set to -1 in the various
+         sys-wrappers for sys_fork, if --child-silent-after-fork=yes
+         is in effect.  That is a signal that we should not produce
+         any more output. */
+      if (VG_(clo_log_fd) >= 0)
+         VG_(write)( VG_(clo_log_fd), msg, nbytes );
    } else {
       Int rc = VG_(write_socket)( VG_(clo_log_fd), msg, nbytes );
       if (rc == -1) {
diff --git a/coregrind/m_main.c b/coregrind/m_main.c
index ca9dc4b..50f6cbb 100644
--- a/coregrind/m_main.c
+++ b/coregrind/m_main.c
@@ -114,7 +114,8 @@
 "    --version                 show version\n"
 "    -q --quiet                run silently; only print error msgs\n"
 "    -v --verbose              be more verbose, incl counts of errors\n"
-"    --trace-children=no|yes   Valgrind-ise child processes? [no]\n"
+"    --trace-children=no|yes   Valgrind-ise child processes (follow execve)? [no]\n"
+"    --child-silent-after-fork=no|yes  omit child output between fork & exec? [no]\n"
 "    --track-fds=no|yes        track open file descriptors? [no]\n"
 "    --time-stamp=no|yes       add timestamps to log messages? [no]\n"
 "    --log-fd=<number>         log messages to file descriptor [2=stderr]\n"
@@ -370,6 +371,8 @@
       else VG_BOOL_CLO(arg, "--time-stamp",       VG_(clo_time_stamp))
       else VG_BOOL_CLO(arg, "--track-fds",        VG_(clo_track_fds))
       else VG_BOOL_CLO(arg, "--trace-children",   VG_(clo_trace_children))
+      else VG_BOOL_CLO(arg, "--child-silent-after-fork",
+                            VG_(clo_child_silent_after_fork))
       else VG_BOOL_CLO(arg, "--trace-sched",      VG_(clo_trace_sched))
       else VG_BOOL_CLO(arg, "--trace-signals",    VG_(clo_trace_signals))
       else VG_BOOL_CLO(arg, "--trace-symtab",     VG_(clo_trace_symtab))
diff --git a/coregrind/m_options.c b/coregrind/m_options.c
index f5ed284..febf82c 100644
--- a/coregrind/m_options.c
+++ b/coregrind/m_options.c
@@ -50,7 +50,8 @@
 HChar* VG_(clo_xml_user_comment) = NULL;
 Bool   VG_(clo_demangle)       = True;
 Bool   VG_(clo_trace_children) = False;
-Int    VG_(clo_log_fd)         = 2;
+Bool   VG_(clo_child_silent_after_fork) = False;
+Int    VG_(clo_log_fd)         = 2; /* must be signed, as -1 is possible. */
 Char*  VG_(clo_log_name)       = NULL;
 Char*  VG_(clo_log_file_qualifier) = NULL;
 Bool   VG_(clo_time_stamp)     = False;
diff --git a/coregrind/m_syswrap/syswrap-aix5.c b/coregrind/m_syswrap/syswrap-aix5.c
index 2ac521a..a5617db 100644
--- a/coregrind/m_syswrap/syswrap-aix5.c
+++ b/coregrind/m_syswrap/syswrap-aix5.c
@@ -1321,13 +1321,22 @@
    SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
 
    if (SUCCESS && RES == 0) {
+      /* child */
       VG_(do_atfork_child)(tid);
 
       /* restore signal mask */
       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+
+      /* If --child-silent-after-fork=yes was specified, set the
+         logging file descriptor to an 'impossible' value.  This is
+         noticed by send_bytes_to_logging_sink in m_libcprint.c, which
+         duly stops writing any further logging output. */
+      if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork))
+         VG_(clo_log_fd) = -1;
    } 
    else 
    if (SUCCESS && RES > 0) {
+      /* parent */
       PRINT("   fork: process %d created child %d\n", VG_(getpid)(), RES);
 
       /* restore signal mask */
diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index 9365394..ccea5c5 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -2895,13 +2895,22 @@
    SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
 
    if (SUCCESS && RES == 0) {
+      /* child */
       VG_(do_atfork_child)(tid);
 
       /* restore signal mask */
       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+
+      /* If --child-silent-after-fork=yes was specified, set the
+         logging file descriptor to an 'impossible' value.  This is
+         noticed by send_bytes_to_logging_sink in m_libcprint.c, which
+         duly stops writing any further logging output. */
+      if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork))
+         VG_(clo_log_fd) = -1;
    } 
    else 
    if (SUCCESS && RES > 0) {
+      /* parent */
       PRINT("   fork: process %d created child %d\n", VG_(getpid)(), RES);
 
       /* restore signal mask */
diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 96cbe37..c1769e5 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -333,6 +333,13 @@
 
       /* restore signal mask */
       VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
+
+      /* If --child-silent-after-fork=yes was specified, set the
+         logging file descriptor to an 'impossible' value.  This is
+         noticed by send_bytes_to_logging_sink in m_libcprint.c, which
+         duly stops writing any further logging output. */
+      if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork))
+         VG_(clo_log_fd) = -1;
    } 
    else 
    if (!res.isError && res.res > 0) {
diff --git a/coregrind/pub_core_options.h b/coregrind/pub_core_options.h
index 09b97fc..15d33f6 100644
--- a/coregrind/pub_core_options.h
+++ b/coregrind/pub_core_options.h
@@ -61,6 +61,12 @@
 extern Bool  VG_(clo_demangle);
 /* Simulate child processes? default: NO */
 extern Bool  VG_(clo_trace_children);
+/* After a fork, the child's output can become confusingly
+   intermingled with the parent's output.  This is especially
+   problematic when VG_(clo_xml) is True.  Setting
+   VG_(clo_child_silent_after_fork) causes children to fall silent
+   after fork() calls. */
+extern Bool  VG_(clo_child_silent_after_fork);
 
 /* Where logging output is to be sent to.