Index: tools/valgrind/fork.patch |
=================================================================== |
--- tools/valgrind/fork.patch (revision 0) |
+++ tools/valgrind/fork.patch (revision 0) |
@@ -0,0 +1,109 @@ |
+Index: coregrind/m_main.c |
+=================================================================== |
+--- coregrind/m_main.c (revision 10399) |
++++ coregrind/m_main.c (working copy) |
+@@ -755,15 +755,26 @@ |
+ If logging to file or a socket, write details of parent PID and |
+ command line args, to help people trying to interpret the |
+ results of a run which encompasses multiple processes. */ |
+-static void print_preamble(Bool logging_to_fd, const char* toolname) |
++ |
++// TODO(timurrrr): we add a non-static declaration of this function since |
++// we need it in coregrind/m_libcproc.c |
++// Should we move it to some header file? |
++void print_preamble(Bool logging_to_fd, const char* toolname); |
++ |
++void print_preamble(Bool logging_to_fd, const char* toolname) |
+ { |
+ HChar* xpre = VG_(clo_xml) ? " <line>" : ""; |
+ HChar* xpost = VG_(clo_xml) ? "</line>" : ""; |
+ Int i; |
++ static const char* last_toolname = NULL; |
+ |
+ vg_assert( VG_(args_for_client) ); |
+ vg_assert( VG_(args_for_valgrind) ); |
++ // This way you may pass toolname == NULL provided the first invocation |
++ // with toolname != NULL takes place in valgrind_main(). |
++ toolname = (toolname == NULL ? last_toolname : toolname); |
+ vg_assert( toolname ); |
++ last_toolname = toolname; |
+ |
+ if (VG_(clo_xml)) { |
+ VG_(message)(Vg_UserMsg, "<?xml version=\"1.0\"?>"); |
+Index: coregrind/m_libcproc.c |
+=================================================================== |
+--- coregrind/m_libcproc.c (revision 10399) |
++++ coregrind/m_libcproc.c (working copy) |
+@@ -33,9 +33,12 @@ |
+ #include "pub_core_vkiscnums.h" |
+ #include "pub_core_libcbase.h" |
+ #include "pub_core_libcassert.h" |
++#include "pub_core_libcfile.h" |
+ #include "pub_core_libcprint.h" |
+ #include "pub_core_libcproc.h" |
+ #include "pub_core_libcsignal.h" |
++#include "pub_core_tooliface.h" |
++#include "pub_core_options.h" |
+ #include "pub_core_seqmatch.h" |
+ #include "pub_core_mallocfree.h" |
+ #include "pub_core_syscall.h" |
+@@ -703,10 +706,59 @@ |
+ (*atforks[i].parent)(tid); |
+ } |
+ |
++// Defined in m_main.c |
++void print_preamble(Bool logging_to_fd, const char* toolname); |
++ |
++// If --log-file=ABC%pXYZ is specified, we'd like to have separate log files |
++// for each forked child. |
++// If %p is present in the --log-file option, this function creates |
++// a new log file and redirects the child's output to it. |
++static void open_new_logfile_for_forked_child(void) |
++{ |
++ SysRes sres; |
++ Int tmp_log_fd = -1; |
++ Char *logfilename, *clo_log_name; |
++ |
++ clo_log_name = VG_(clo_log_name); |
++ if (clo_log_name == NULL || !VG_(strstr)(clo_log_name, "%p")) { |
++ // Don't create new log streams unless --log-file=ABC%pXYZ is specified. |
++ return; |
++ } |
++ |
++ logfilename = VG_(expand_file_name)("--log-file", clo_log_name); |
++ sres = VG_(open) (logfilename, |
++ VKI_O_CREAT | VKI_O_WRONLY | VKI_O_TRUNC, |
++ VKI_S_IRUSR | VKI_S_IWUSR); |
++ if (!sr_isError(sres)) { |
++ tmp_log_fd = sr_Res(sres); |
++ // Move log_fd into the safe range, |
++ // so it doesn't conflict with any app fds. |
++ tmp_log_fd = VG_(fcntl) (tmp_log_fd, VKI_F_DUPFD, VG_(fd_hard_limit)); |
++ if (tmp_log_fd >= 0) { |
++ VG_(clo_log_fd) = tmp_log_fd; |
++ VG_(fcntl) (VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC); |
++ } else { |
++ VG_(message) (Vg_UserMsg, |
++ "valgrind: failed to move logfile fd into safe range, " |
++ "using stderr"); |
++ VG_(clo_log_fd) = 2; // stderr |
++ } |
++ } else { |
++ VG_(message) (Vg_UserMsg, |
++ "Can't create log file '%s' (%s); giving up!", |
++ logfilename, VG_(strerror) (sr_Err(sres))); |
++ VG_(core_panic)("Error creating log file for child process"); |
++ } |
++ |
++ print_preamble(False, NULL); |
++} |
++ |
+ void VG_(do_atfork_child)(ThreadId tid) |
+ { |
+ Int i; |
+ |
++ open_new_logfile_for_forked_child(); |
++ |
+ for (i = 0; i < n_atfork; i++) |
+ if (atforks[i].child != NULL) |
+ (*atforks[i].child)(tid); |