Index: coregrind/m_syswrap/syswrap-generic.c =================================================================== --- coregrind/m_syswrap/syswrap-generic.c (revision 10880) +++ coregrind/m_syswrap/syswrap-generic.c (working copy) @@ -2563,6 +2563,11 @@ } else { path = (Char*)ARG1; + if (VG_(clo_xml)) { + VG_(printf_xml)("\n\n\n\n\n"); + } else { + VG_(umsg)("execv called - the tool will now quit\n"); + } } // Set up the child's environment. @@ -4103,4 +4108,3 @@ /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/ - Index: coregrind/pub_core_libcfile.h =================================================================== --- coregrind/pub_core_libcfile.h (revision 10880) +++ coregrind/pub_core_libcfile.h (working copy) @@ -41,6 +41,7 @@ /* Move an fd into the Valgrind-safe range */ extern Int VG_(safe_fd) ( Int oldfd ); +extern Int reopen_output_fd(Bool xml); extern Int VG_(fcntl) ( Int fd, Int cmd, Addr arg ); /* Convert an fd into a filename */ Index: coregrind/m_main.c =================================================================== --- coregrind/m_main.c (revision 10880) +++ coregrind/m_main.c (working copy) @@ -313,6 +313,64 @@ } } +Int reopen_output_fd(Bool xml) { + // Returns FD + Char *filename = NULL; + Char *fsname_unexpanded = xml ? VG_(clo_xml_fname_unexpanded) : + VG_(clo_log_fname_unexpanded); + const Char *output_type = xml ? "xml" : "log"; + Int ret = -1; + SysRes sres; + + vg_assert(fsname_unexpanded != NULL); + vg_assert(VG_(strlen)(fsname_unexpanded) <= 900); /* paranoia */ + + // Nb: we overwrite an existing file of this name without asking + // any questions. + filename = VG_(expand_file_name)(xml ? "--xml-file" : "--log-file", + fsname_unexpanded); + sres = VG_(open)(filename, + VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC, + VKI_S_IRUSR|VKI_S_IWUSR); + if (!sr_isError(sres)) { + ret = sr_Res(sres); + if (xml) + VG_(clo_xml_fname_expanded) = filename; + else + VG_(clo_log_fname_expanded) = filename; + + /* strdup here is probably paranoid overkill, but ... */ + // TODO: do we need to do anything with it? + /* *fsname_unexpanded = VG_(strdup)( "main.mpclo.2", + xml_fsname_unexpanded ); */ + } else { + VG_(message)(Vg_UserMsg, + "Can't create %s file '%s' (%s); giving up!\n", + output_type, filename, VG_(strerror)(sr_Err(sres))); + VG_(err_bad_option)( + "--[xml|log]-file= (didn't work out for some reason.)"); + /*NOTREACHED*/ + } + + return ret; +} + +static Int move_fd_into_safe_range(Int fd, Bool xml) { + OutputSink *sink = xml ? &(VG_(xml_output_sink)) : &(VG_(log_output_sink)); + // Move fd into the safe range, so it doesn't conflict with any app fds. + fd = VG_(fcntl)(fd, VKI_F_DUPFD, VG_(fd_hard_limit)); + if (fd < 0) { + VG_(printf)("valgrind: failed to move %s file fd " + "into safe range, using stderr\n", xml ? "XML" : "log"); + sink->fd = 2; // stderr + sink->is_socket = False; + } else { + sink->fd = fd; + VG_(fcntl)(fd, VKI_F_SETFD, VKI_FD_CLOEXEC); + } + return fd; +} + /* The main processing for command line options. See comments above on early_process_cmd_line_options. @@ -339,13 +397,11 @@ */ static void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd, - /*OUT*/Char** xml_fname_unexpanded, const HChar* toolname ) { // VG_(clo_log_fd) is used by all the messaging. It starts as 2 (stderr) // and we cannot change it until we know what we are changing it to is // ok. So we have tmp_log_fd to hold the tmp fd prior to that point. - SysRes sres; Int i, tmp_log_fd, tmp_xml_fd; Int toolname_len = VG_(strlen)(toolname); Char* tmp_str; // Used in a couple of places. @@ -514,9 +570,13 @@ else if VG_STR_CLO(arg, "--log-file", log_fsname_unexpanded) { log_to = VgLogTo_File; + VG_(clo_log_fname_unexpanded) = + VG_(strdup)("", log_fsname_unexpanded); } else if VG_STR_CLO(arg, "--xml-file", xml_fsname_unexpanded) { xml_to = VgLogTo_File; + VG_(clo_xml_fname_unexpanded) = + VG_(strdup)("", xml_fsname_unexpanded); } else if VG_STR_CLO(arg, "--log-socket", log_fsname_unexpanded) { @@ -716,29 +776,7 @@ break; case VgLogTo_File: { - Char* logfilename; - - vg_assert(log_fsname_unexpanded != NULL); - vg_assert(VG_(strlen)(log_fsname_unexpanded) <= 900); /* paranoia */ - - // Nb: we overwrite an existing file of this name without asking - // any questions. - logfilename = VG_(expand_file_name)("--log-file", - log_fsname_unexpanded); - 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); - VG_(clo_log_fname_expanded) = logfilename; - } else { - VG_(message)(Vg_UserMsg, - "Can't create log file '%s' (%s); giving up!\n", - logfilename, VG_(strerror)(sr_Err(sres))); - VG_(err_bad_option)( - "--log-file= (didn't work out for some reason.)"); - /*NOTREACHED*/ - } + tmp_log_fd = reopen_output_fd(False); break; } @@ -784,32 +822,7 @@ break; case VgLogTo_File: { - Char* xmlfilename; - - vg_assert(xml_fsname_unexpanded != NULL); - vg_assert(VG_(strlen)(xml_fsname_unexpanded) <= 900); /* paranoia */ - - // Nb: we overwrite an existing file of this name without asking - // any questions. - xmlfilename = VG_(expand_file_name)("--xml-file", - xml_fsname_unexpanded); - sres = VG_(open)(xmlfilename, - VKI_O_CREAT|VKI_O_WRONLY|VKI_O_TRUNC, - VKI_S_IRUSR|VKI_S_IWUSR); - if (!sr_isError(sres)) { - tmp_xml_fd = sr_Res(sres); - VG_(clo_xml_fname_expanded) = xmlfilename; - /* strdup here is probably paranoid overkill, but ... */ - *xml_fname_unexpanded = VG_(strdup)( "main.mpclo.2", - xml_fsname_unexpanded ); - } else { - VG_(message)(Vg_UserMsg, - "Can't create XML file '%s' (%s); giving up!\n", - xmlfilename, VG_(strerror)(sr_Err(sres))); - VG_(err_bad_option)( - "--xml-file= (didn't work out for some reason.)"); - /*NOTREACHED*/ - } + tmp_xml_fd = reopen_output_fd(True); break; } @@ -864,18 +877,7 @@ // Finalise the output fds: the log fd .. if (tmp_log_fd >= 0) { - // 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_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd " - "into safe range, using stderr\n"); - VG_(log_output_sink).fd = 2; // stderr - VG_(log_output_sink).is_socket = False; - } else { - VG_(log_output_sink).fd = tmp_log_fd; - VG_(fcntl)(VG_(log_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC); - } + tmp_log_fd = move_fd_into_safe_range(tmp_log_fd, False); } else { // If they said --log-fd=-1, don't print anything. Plausible for use in // regression testing suites that use client requests to count errors. @@ -886,18 +888,7 @@ // Finalise the output fds: and the XML fd .. if (tmp_xml_fd >= 0) { - // Move xml_fd into the safe range, so it doesn't conflict with - // any app fds. - tmp_xml_fd = VG_(fcntl)(tmp_xml_fd, VKI_F_DUPFD, VG_(fd_hard_limit)); - if (tmp_xml_fd < 0) { - VG_(message)(Vg_UserMsg, "valgrind: failed to move XML file fd " - "into safe range, using stderr\n"); - VG_(xml_output_sink).fd = 2; // stderr - VG_(xml_output_sink).is_socket = False; - } else { - VG_(xml_output_sink).fd = tmp_xml_fd; - VG_(fcntl)(VG_(xml_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC); - } + tmp_xml_fd = move_fd_into_safe_range(tmp_xml_fd, True); } else { // If they said --xml-fd=-1, don't print anything. Plausible for use in // regression testing suites that use client requests to count errors. @@ -989,9 +980,12 @@ 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, - Char* xml_fname_unexpanded, - const HChar* 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 HChar* toolname ); + +void print_preamble ( Bool logging_to_fd, const HChar* toolname ) { Int i; HChar* xpre = VG_(clo_xml) ? " " : ""; @@ -999,9 +993,15 @@ UInt (*umsg_or_xml)( const HChar*, ... ) = VG_(clo_xml) ? VG_(printf_xml) : VG_(umsg); + 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_(printf_xml)("\n"); @@ -1013,7 +1013,7 @@ VG_(printf_xml)("\n"); } - if (VG_(clo_xml) || VG_(clo_verbosity > 0)) { + if (VG_(clo_xml) || VG_(clo_verbosity) > 0) { if (VG_(clo_xml)) VG_(printf_xml)("\n"); @@ -1067,6 +1067,7 @@ } else if (VG_(clo_xml)) { + Char *xml_fname_unexpanded = VG_(clo_xml_fname_unexpanded); VG_(printf_xml)("\n"); VG_(printf_xml)("%d\n", VG_(getpid)()); VG_(printf_xml)("%d\n", VG_(getppid)()); @@ -1374,7 +1375,6 @@ Int need_help = 0; // 0 = no, 1 = --help, 2 = --help-debug ThreadId tid_main = VG_INVALID_THREADID; Bool logging_to_fd = False; - Char* xml_fname_unexpanded = NULL; Int loglevel, i; struct vki_rlimit zero = { 0, 0 }; XArray* addr2dihandle = NULL; @@ -1872,8 +1872,7 @@ VG_(debugLog)(1, "main", "(main_) Process Valgrind's command line options, " "setup logging\n"); - main_process_cmd_line_options ( &logging_to_fd, &xml_fname_unexpanded, - toolname ); + main_process_cmd_line_options ( &logging_to_fd, toolname ); //-------------------------------------------------------------- // Zeroise the millisecond counter by doing a first read of it. @@ -1886,10 +1885,10 @@ // p: tl_pre_clo_init [for 'VG_(details).name' and friends] // p: main_process_cmd_line_options() // [for VG_(clo_verbosity), VG_(clo_xml), - // logging_to_fd, xml_fname_unexpanded] + // logging_to_fd] //-------------------------------------------------------------- VG_(debugLog)(1, "main", "Print the preamble...\n"); - print_preamble(logging_to_fd, xml_fname_unexpanded, toolname); + print_preamble(logging_to_fd, toolname); VG_(debugLog)(1, "main", "...finished the preamble\n"); //-------------------------------------------------------------- Index: coregrind/m_libcproc.c =================================================================== --- coregrind/m_libcproc.c (revision 10880) +++ 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" @@ -708,10 +711,39 @@ (*atforks[i].parent)(tid); } +// Defined in m_main.c +void print_preamble(Bool logging_to_fd, const char* toolname); + +Char* VG_(clo_log_fname_unexpanded) = NULL; +Char* VG_(clo_xml_fname_unexpanded) = NULL; + +// 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) +{ + Int tmp_fd = -1; + + if (VG_(log_output_sink).is_socket == False && VG_(clo_log_fname_unexpanded) != NULL) { + tmp_fd = reopen_output_fd(False); + VG_(log_output_sink).fd = VG_(safe_fd)(tmp_fd); + } + + if (VG_(xml_output_sink).is_socket == False && VG_(clo_xml_fname_unexpanded) != NULL) { + tmp_fd = reopen_output_fd(True); + VG_(xml_output_sink).fd = VG_(safe_fd)(tmp_fd); + } + + 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); Index: coregrind/pub_core_options.h =================================================================== --- coregrind/pub_core_options.h (revision 10880) +++ coregrind/pub_core_options.h (working copy) @@ -74,6 +74,9 @@ extern Char* VG_(clo_log_fname_expanded); extern Char* VG_(clo_xml_fname_expanded); +extern Char* VG_(clo_log_fname_unexpanded); +extern Char* VG_(clo_xml_fname_unexpanded); + /* Add timestamps to log messages? default: NO */ extern Bool VG_(clo_time_stamp);