From d9b5337f4b0d793bcc3a4cd9a71883504df289fc Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Sun, 27 Oct 2002 20:28:29 +0000 Subject: [PATCH] Implement --logfile=, which causes all the log output to be written to ".pid". Useful for tracing trees of processes. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1269 --- coregrind/vg_include.h | 37 +++++++++++++++++--- coregrind/vg_main.c | 79 ++++++++++++++++++++++++++++++++++++++++-- coregrind/vg_mylibc.c | 9 +++++ include/vg_skin.h | 3 +- 4 files changed, 120 insertions(+), 8 deletions(-) diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 5de1d30f6..47c96b605 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -47,8 +47,9 @@ #include "vg_constants.h" -/* All stuff visible to core and skins goes in vg_skin.h. Things visible - * to core but private to skins go here. */ +/* All stuff visible to core and skins goes in vg_skin.h. Things + * visible to core but not visible to any skins should go in this + * file, vg_include.h. */ #include "vg_skin.h" /* Total number of spill slots available for allocation, if a TempReg @@ -152,6 +153,15 @@ #define VG_CLO_MAX_SFILES 10 +/* Describes where logging output is to be sent. */ +typedef + enum { + VgLogTo_Fd, + VgLogTo_File, + VgLogTo_Socket + } VgLogTo; + + /* Should we stop collecting errors if too many appear? default: YES */ extern Bool VG_(clo_error_limit); /* Enquire about whether to attach to GDB at errors? default: NO */ @@ -168,8 +178,27 @@ extern Bool VG_(clo_sloppy_malloc); extern Int VG_(clo_alignment); /* Simulate child processes? default: NO */ extern Bool VG_(clo_trace_children); -/* The file id on which we send all messages. default: 2 (stderr). */ -extern Int VG_(clo_logfile_fd); + +/* Where logging output is to be sent to. + + When log_to == VgLogTo_Fd, clo_logfile_fd holds the file id, and is + taken from the command line. clo_logfile_name is irrelevant. + + When log_to == VgLogTo_File, clo_logfile_name holds the logfile + name, and is taken from the command line. clo_logfile_fd is then + made to hold the relevant file id, by opening clo_logfile_name + (concatenated with the process ID) for writing. + + When log_to == VgLogTo_Socket, clo_logfile_name holds the + hostname:portnumber pair, and is taken from the command line. + clo_logfile_fd is then made to hold the relevant file handle, by + opening a connection to said hostname:portnumber pair. + + Global default is to set log_to == VgLogTo_Fd and logfile_fd == 2 + (stderr). */ +extern VgLogTo VG_(clo_log_to); +extern Int VG_(clo_logfile_fd); +extern Char* VG_(clo_logfile_name); /* The number of suppression files specified. */ extern Int VG_(clo_n_suppressions); diff --git a/coregrind/vg_main.c b/coregrind/vg_main.c index b08f46395..d26bc29b2 100644 --- a/coregrind/vg_main.c +++ b/coregrind/vg_main.c @@ -540,7 +540,12 @@ Bool VG_(clo_demangle) = True; Bool VG_(clo_sloppy_malloc) = False; Int VG_(clo_alignment) = 4; Bool VG_(clo_trace_children) = False; -Int VG_(clo_logfile_fd) = 2; + +/* See big comment in vg_include.h for meaning of these three. */ +VgLogTo VG_(clo_log_to) = VgLogTo_Fd; +Int VG_(clo_logfile_fd) = 2; +Char* VG_(clo_logfile_name) = NULL; + Int VG_(clo_n_suppressions) = 0; Char* VG_(clo_suppressions)[VG_CLO_MAX_SFILES]; Bool VG_(clo_profile) = False; @@ -583,6 +588,7 @@ static Char vg_cmdline_copy[M_VG_CMDLINE_STRLEN]; void VG_(bad_option) ( Char* opt ) { VG_(shutdown_logging)(); + VG_(clo_log_to) = VgLogTo_Fd; VG_(clo_logfile_fd) = 2; /* stderr */ VG_(printf)("valgrind.so: Bad option `%s'; aborting.\n", opt); VG_(exit)(1); @@ -591,6 +597,7 @@ void VG_(bad_option) ( Char* opt ) static void config_error ( Char* msg ) { VG_(shutdown_logging)(); + VG_(clo_log_to) = VgLogTo_Fd; VG_(clo_logfile_fd) = 2; /* stderr */ VG_(printf)( "valgrind.so: Startup or configuration error:\n %s\n", msg); @@ -602,6 +609,7 @@ static void config_error ( Char* msg ) static void args_grok_error ( Char* msg ) { VG_(shutdown_logging)(); + VG_(clo_log_to) = VgLogTo_Fd; VG_(clo_logfile_fd) = 2; /* stderr */ VG_(printf)("valgrind.so: When searching for " "client's argc/argc/envp:\n\t%s\n", msg); @@ -628,6 +636,7 @@ static void usage ( void ) " --trace-children=no|yes Valgrind-ise child processes? [no]\n" " --run-libc-freeres=no|yes Free up glibc memory at exit? [yes]\n" " --logfile-fd= file descriptor for messages [2=stderr]\n" +" --logfile= log messages to .pid\n" " --suppressions= suppress errors described in\n" " suppressions file \n" " --weird-hacks=hack1,hack2,... [no hacks selected]\n" @@ -675,6 +684,7 @@ static void usage ( void ) VG_(printf)(usage2, VG_EMAIL_ADDR); VG_(shutdown_logging)(); + VG_(clo_log_to) = VgLogTo_Fd; VG_(clo_logfile_fd) = 2; /* stderr */ VG_(exit)(1); } @@ -886,8 +896,16 @@ static void process_cmd_line_options ( void ) else if (STREQN(15, argv[i], "--sanity-level=")) VG_(sanity_level) = (Int)VG_(atoll)(&argv[i][15]); - else if (STREQN(13, argv[i], "--logfile-fd=")) + else if (STREQN(13, argv[i], "--logfile-fd=")) { + VG_(clo_log_to) = VgLogTo_Fd; + VG_(clo_logfile_name) = NULL; eventually_logfile_fd = (Int)VG_(atoll)(&argv[i][13]); + } + + else if (STREQN(10, argv[i], "--logfile=")) { + VG_(clo_log_to) = VgLogTo_File; + VG_(clo_logfile_name) = &argv[i][10]; + } else if (STREQN(15, argv[i], "--suppressions=")) { if (VG_(clo_n_suppressions) >= VG_CLO_MAX_SFILES) { @@ -1020,7 +1038,50 @@ static void process_cmd_line_options ( void ) VG_(bad_option)("--gdb-attach=yes and --trace-children=yes"); } - VG_(clo_logfile_fd) = eventually_logfile_fd; + /* Set up logging now. After this is done, VG_(clo_logfile_fd) + should be connected to whatever sink has been selected, and we + indiscriminately chuck stuff into it without worrying what the + nature of it is. Oh the wonder of Unix streams. */ + + /* So far we should be still attached to stderr, so we can show on + the terminal any problems to do with processing command line + opts. */ + vg_assert(VG_(clo_logfile_fd) == 2 /* stderr */); + + switch (VG_(clo_log_to)) { + case VgLogTo_Socket: + VG_(core_panic)("VgLogTo_Socket ?!"); + break; + case VgLogTo_Fd: + vg_assert(VG_(clo_logfile_name) == NULL); + VG_(clo_logfile_fd) = eventually_logfile_fd; + break; + case VgLogTo_File: { + Char logfilename[1000]; + vg_assert(VG_(clo_logfile_name) != NULL); + vg_assert(VG_(strlen)(VG_(clo_logfile_name)) <= 900); /* paranoia */ + VG_(sprintf)(logfilename, "%s.pid%d", + VG_(clo_logfile_name), VG_(getpid)() ); + eventually_logfile_fd + = VG_(open)(logfilename, VKI_O_CREAT|VKI_O_WRONLY, + VKI_S_IRUSR|VKI_S_IWUSR); + if (eventually_logfile_fd != -1) { + VG_(clo_logfile_fd) = eventually_logfile_fd; + } else { + VG_(message)(Vg_UserMsg, + "Can't create/open log file `%s.pid%d'; giving up!", + VG_(clo_logfile_name), VG_(getpid)()); + VG_(bad_option)( + "--logfile= didn't work out for some reason."); + } + break; + } + } + + /* Ok, the logging sink is running now. Print a suitable preamble. + 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. */ if (VG_(clo_verbosity > 0)) { /* Skin details */ @@ -1040,7 +1101,18 @@ static void process_cmd_line_options ( void ) "Copyright (C) 2000-2002, and GNU GPL'd, by Julian Seward."); } + if (VG_(clo_log_to) != VgLogTo_Fd) { + VG_(message)(Vg_UserMsg, ""); + VG_(message)(Vg_UserMsg, + "My PID = %d, parent PID = %d. Prog and args are:", + VG_(getpid)(), VG_(getppid)() ); + for (i = 0; i < VG_(client_argc); i++) + VG_(message)(Vg_UserMsg, " %s", VG_(client_argv)[i]); + } + if (VG_(clo_verbosity) > 1) { + if (VG_(clo_log_to) != VgLogTo_Fd) + VG_(message)(Vg_UserMsg, ""); VG_(message)(Vg_UserMsg, "Startup, with flags:"); for (i = 0; i < argc; i++) { VG_(message)(Vg_UserMsg, " %s", argv[i]); @@ -1051,6 +1123,7 @@ static void process_cmd_line_options ( void ) (VG_(needs).core_errors || VG_(needs).skin_errors)) { config_error("No error-suppression files were specified."); } + } /* --------------------------------------------------------------------- diff --git a/coregrind/vg_mylibc.c b/coregrind/vg_mylibc.c index 75dedbc28..05f662f66 100644 --- a/coregrind/vg_mylibc.c +++ b/coregrind/vg_mylibc.c @@ -1193,6 +1193,7 @@ Char* VG_(getenv) ( Char* varname ) return NULL; } + /* You'd be amazed how many places need to know the current pid. */ Int VG_(getpid) ( void ) { @@ -1202,6 +1203,14 @@ Int VG_(getpid) ( void ) return res; } +Int VG_(getppid) ( void ) +{ + Int res; + res = vg_do_syscall0(__NR_getppid); + return res; +} + + /* Return -1 if error, else 0. NOTE does not indicate return code of child! */ Int VG_(system) ( Char* cmd ) diff --git a/include/vg_skin.h b/include/vg_skin.h index 819d1539f..ab191b766 100644 --- a/include/vg_skin.h +++ b/include/vg_skin.h @@ -364,7 +364,8 @@ extern Int VG_(log2) ( Int x ); /* ------------------------------------------------------------------ */ /* unistd.h, fcntl.h, sys/stat.h */ -extern Int VG_(getpid) ( void ); +extern Int VG_(getpid) ( void ); +extern Int VG_(getppid) ( void ); extern Int VG_(open) ( const Char* pathname, Int flags, Int mode ); extern Int VG_(read) ( Int fd, void* buf, Int count);