| 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<execv/>\n\n</valgrindoutput>\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,48 @@ |
| } |
| } |
| |
| +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=<file> (didn't work out for some reason.)"); |
| + /*NOTREACHED*/ |
| + } |
| + |
| + return ret; |
| +} |
| + |
| /* The main processing for command line options. See comments above |
| on early_process_cmd_line_options. |
| |
| @@ -339,13 +381,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 +554,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 +760,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=<file> (didn't work out for some reason.)"); |
| - /*NOTREACHED*/ |
| - } |
| + tmp_log_fd = reopen_output_fd(False); |
| break; |
| } |
| |
| @@ -784,32 +806,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=<file> (didn't work out for some reason.)"); |
| - /*NOTREACHED*/ |
| - } |
| + tmp_xml_fd = reopen_output_fd(True); |
| break; |
| } |
| |
| @@ -864,18 +861,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); |
| - } |
| + VG_(log_output_sink).fd = tmp_log_fd = VG_(safe_fd)(tmp_log_fd); |
| } 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 +872,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); |
| - } |
| + VG_(xml_output_sink).fd = tmp_xml_fd = VG_(safe_fd)(tmp_xml_fd); |
| } 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 +964,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) ? " <line>" : ""; |
| @@ -999,9 +977,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)("<?xml version=\"1.0\"?>\n"); |
| @@ -1013,7 +997,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)("<preamble>\n"); |
| @@ -1067,6 +1051,7 @@ |
| } |
| else |
| if (VG_(clo_xml)) { |
| + Char *xml_fname_unexpanded = VG_(clo_xml_fname_unexpanded); |
| VG_(printf_xml)("\n"); |
| VG_(printf_xml)("<pid>%d</pid>\n", VG_(getpid)()); |
| VG_(printf_xml)("<ppid>%d</ppid>\n", VG_(getppid)()); |
| @@ -1374,7 +1359,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 +1856,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 +1869,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); |
| |