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) {
" --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"
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))
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;
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 */
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 */
/* 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) {
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.