Implement --logfile=<file>, which causes all the log output to be

written to "<file>.pid<pid>".  Useful for tracing trees of processes.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1269
This commit is contained in:
Julian Seward 2002-10-27 20:28:29 +00:00
parent a2b7a4f408
commit d9b5337f4b
4 changed files with 120 additions and 8 deletions

View File

@ -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);

View File

@ -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=<number> file descriptor for messages [2=stderr]\n"
" --logfile=<file> log messages to <file>.pid<pid>\n"
" --suppressions=<filename> suppress errors described in\n"
" suppressions file <filename>\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=<file> 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.");
}
}
/* ---------------------------------------------------------------------

View File

@ -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 )

View File

@ -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);