|
From: <sv...@va...> - 2009-05-10 11:10:12
|
Author: sewardj
Date: 2009-05-10 12:10:08 +0100 (Sun, 10 May 2009)
New Revision: 9820
Log:
Add a second output channel (file descriptor), to be used for XML
output. This gives the normal text output and the XML output their
own independent file descriptors. It solves two longstanding
problems with XML output:
* in XML mode, it was not possible to emit any text output at
all, even critical warning messages, eg, to say that the
debuginfo of some object is corrupted or unreadable
* in XML mode, if any such messages did happen to get emitted
(as is inevitably the case) then tools parsing the XML would
break.
So now there are two output channels, the normal (text) channel and
the XML channel. These are specified as follows:
text channel: --log-fd=, --log-file= or --log-socket= (as before)
XML channel: --xml-fd=, --xml-file= or --xml-socket=
Note that these merely specify where the relevant kind of output
is to be sent. They have no effect on what kind of output (text
or XML) the tool actually produces. That decision is still
controlled using the --xml= flag.
Mostly the command line arg changes should be invisible to users;
the normal --log-{fd,file,socket} work exactly as before. The
only obvious change is that to get XML output into a file, you
need --xml=yes --xml-file=... instead of --xml=yes --log-file=yes
now.
There are some other associated cleanups:
* in m_libcprint, some of the routines are now parameterised also
by an OutputSink structure, which indicates where the output is
to be sent.
* in m_options, various logging related VG_(clo_...) variables
have been removed, because they're not needed. m_main examines
the command line arguments, and sets up the OutputSinks for
text and XML output; but m_libcprint "owns" those OutputSinks,
not m_options.
At present the XML outputting is not hooked up to the new mechanism.
Modified:
branches/MESSAGING_TIDYUP/coregrind/m_coredump/coredump-elf.c
branches/MESSAGING_TIDYUP/coregrind/m_libcprint.c
branches/MESSAGING_TIDYUP/coregrind/m_main.c
branches/MESSAGING_TIDYUP/coregrind/m_options.c
branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-generic.c
branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-linux.c
branches/MESSAGING_TIDYUP/coregrind/pub_core_libcprint.h
branches/MESSAGING_TIDYUP/coregrind/pub_core_options.h
branches/MESSAGING_TIDYUP/include/pub_tool_libcprint.h
Modified: branches/MESSAGING_TIDYUP/coregrind/m_coredump/coredump-elf.c
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/m_coredump/coredump-elf.c 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/m_coredump/coredump-elf.c 2009-05-10 11:10:08 UTC (rev 9820)
@@ -272,11 +272,11 @@
Addr *seg_starts;
Int n_seg_starts;
- if (VG_(clo_log_name) != NULL) {
+ if (VG_(clo_log_fname_expanded) != NULL) {
coreext = ".core";
basename = VG_(expand_file_name)(
"--log-file (while creating core filename)",
- VG_(clo_log_name));
+ VG_(clo_log_fname_expanded));
}
vg_assert(coreext);
Modified: branches/MESSAGING_TIDYUP/coregrind/m_libcprint.c
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/m_libcprint.c 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/m_libcprint.c 2009-05-10 11:10:08 UTC (rev 9820)
@@ -40,36 +40,40 @@
#include "valgrind.h" // For RUNNING_ON_VALGRIND
-
/* ---------------------------------------------------------------------
Writing to file or a socket
------------------------------------------------------------------ */
-/* Tell the logging mechanism whether we are logging to a file
- descriptor or a socket descriptor. */
-Bool VG_(logging_to_socket) = False;
-
+/* The destination sinks for normal and XML output. These have their
+ initial values here; they are set to final values by
+ m_main.main_process_cmd_line_options(). See comment at the top of
+ that function for the associated logic. */
+OutputSink VG_(log_output_sink) = { 2, False }; /* 2 = stderr */
+OutputSink VG_(xml_output_sink) = { -1, False }; /* disabled */
+
/* Do the low-level send of a message to the logging sink. */
-static void send_bytes_to_logging_sink ( Char* msg, Int nbytes )
+static
+void send_bytes_to_logging_sink ( OutputSink* sink, Char* msg, Int nbytes )
{
- if (!VG_(logging_to_socket)) {
- /* VG_(clo_log_fd) could have been set to -1 in the various
+ if (sink->is_socket) {
+ Int rc = VG_(write_socket)( sink->fd, msg, nbytes );
+ if (rc == -1) {
+ // For example, the listener process died. Switch back to stderr.
+ sink->is_socket = False;
+ sink->fd = 2;
+ VG_(write)( sink->fd, msg, nbytes );
+ }
+ } else {
+ /* sink->fd could have been set to -1 in the various
sys-wrappers for sys_fork, if --child-silent-after-fork=yes
is in effect. That is a signal that we should not produce
any more output. */
- if (VG_(clo_log_fd) >= 0)
- VG_(write)( VG_(clo_log_fd), msg, nbytes );
- } else {
- Int rc = VG_(write_socket)( VG_(clo_log_fd), msg, nbytes );
- if (rc == -1) {
- // For example, the listener process died. Switch back to stderr.
- VG_(logging_to_socket) = False;
- VG_(clo_log_fd) = 2;
- VG_(write)( VG_(clo_log_fd), msg, nbytes );
- }
+ if (sink->fd >= 0)
+ VG_(write)( sink->fd, msg, nbytes );
}
}
+
/* ---------------------------------------------------------------------
printf() and friends
------------------------------------------------------------------ */
@@ -78,8 +82,9 @@
typedef
struct {
- HChar buf[512];
- Int buf_used;
+ HChar buf[512];
+ Int buf_used;
+ OutputSink* sink;
}
printf_buf_t;
@@ -90,7 +95,7 @@
printf_buf_t *b = (printf_buf_t *)p;
if (b->buf_used > sizeof(b->buf) - 2 ) {
- send_bytes_to_logging_sink( b->buf, b->buf_used );
+ send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
b->buf_used = 0;
}
b->buf[b->buf_used++] = c;
@@ -98,57 +103,75 @@
tl_assert(b->buf_used < sizeof(b->buf));
}
-static UInt vprintf_to_buf ( printf_buf_t *prbuf,
+static UInt vprintf_to_buf ( printf_buf_t* b,
const HChar *format, va_list vargs )
{
UInt ret = 0;
-
- if (VG_(clo_log_fd) >= 0) {
+ if (b->sink->fd >= 0) {
ret = VG_(debugLog_vprintf)
- ( add_to__printf_buf, prbuf, format, vargs );
+ ( add_to__printf_buf, b, format, vargs );
}
return ret;
}
-UInt VG_(vprintf) ( const HChar *format, va_list vargs )
+static UInt vprintf_WRK ( OutputSink* sink,
+ const HChar *format, va_list vargs )
{
- UInt ret = 0;
- printf_buf_t myprintf_buf = {"",0};
-
- ret = vprintf_to_buf(&myprintf_buf, format, vargs);
+ printf_buf_t myprintf_buf
+ = { "", 0, sink };
+ UInt ret
+ = vprintf_to_buf(&myprintf_buf, format, vargs);
// Write out any chars left in the buffer.
if (myprintf_buf.buf_used > 0) {
- send_bytes_to_logging_sink( myprintf_buf.buf,
+ send_bytes_to_logging_sink( myprintf_buf.sink,
+ myprintf_buf.buf,
myprintf_buf.buf_used );
}
return ret;
}
+UInt VG_(vprintf) ( const HChar *format, va_list vargs )
+{
+ return vprintf_WRK( &VG_(log_output_sink), format, vargs );
+}
+
UInt VG_(printf) ( const HChar *format, ... )
{
UInt ret;
va_list vargs;
+ va_start(vargs, format);
+ ret = VG_(vprintf)(format, vargs);
+ va_end(vargs);
+ return ret;
+}
+UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
+{
+ return vprintf_WRK( &VG_(xml_output_sink), format, vargs );
+}
+
+UInt VG_(printf_xml) ( const HChar *format, ... )
+{
+ UInt ret;
+ va_list vargs;
va_start(vargs, format);
ret = VG_(vprintf)(format, vargs);
va_end(vargs);
+ return ret;
+}
+/* An exact clone of VG_(printf_xml), unfortunately. */
+UInt VG_(printf_xml_no_f_c) ( const HChar *format, ... )
+{
+ UInt ret;
+ va_list vargs;
+ va_start(vargs, format);
+ ret = VG_(vprintf)(format, vargs);
+ va_end(vargs);
return ret;
}
-//static UInt printf_to_buf ( printf_buf_t* prbuf, const HChar *format, ... )
-//{
-// UInt ret;
-// va_list vargs;
-//
-// va_start(vargs, format);
-// ret = vprintf_to_buf(prbuf, format, vargs);
-// va_end(vargs);
-//
-// return ret;
-//}
-
/* --------- sprintf --------- */
/* If we had an explicit buf structure here, it would contain only one
@@ -179,11 +202,9 @@
{
UInt ret;
va_list vargs;
-
va_start(vargs,format);
ret = VG_(vsprintf)(buf, format, vargs);
va_end(vargs);
-
return ret;
}
@@ -228,11 +249,9 @@
{
UInt ret;
va_list vargs;
-
va_start(vargs,format);
ret = VG_(vsnprintf)(buf, size, format, vargs);
va_end(vargs);
-
return ret;
}
@@ -342,12 +361,17 @@
Int buf_used;
Bool atLeft; /* notionally, is the next char position at the
leftmost column? */
+ /* Current message kind - changes from call to call */
VgMsgKind kind;
+ /* PID; acquired just once and stays constant */
Int my_pid;
+ /* destination */
+ OutputSink* sink;
}
vmessage_buf_t;
-static vmessage_buf_t vmessage_buf = {"", 0, True, Vg_UserMsg, -1};
+static vmessage_buf_t vmessage_buf
+ = { "", 0, True, Vg_UserMsg, -1, &VG_(log_output_sink) };
// Adds a single char to the buffer. We aim to have at least 128
@@ -413,7 +437,7 @@
b->buf[b->buf_used] = 0;
if (b->buf_used >= sizeof(b->buf) - 128) {
- send_bytes_to_logging_sink( b->buf, b->buf_used );
+ send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
b->buf_used = 0;
}
@@ -448,7 +472,7 @@
in later messages, so don't bother to flush it right now. */
if (b->atLeft && b->buf_used > 0) {
- send_bytes_to_logging_sink( b->buf, b->buf_used );
+ send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
b->buf_used = 0;
}
@@ -482,7 +506,7 @@
void VG_(message_flush) ( void )
{
vmessage_buf_t* b = &vmessage_buf;
- send_bytes_to_logging_sink( b->buf, b->buf_used );
+ send_bytes_to_logging_sink( b->sink, b->buf, b->buf_used );
b->buf_used = 0;
}
Modified: branches/MESSAGING_TIDYUP/coregrind/m_main.c
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/m_main.c 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/m_main.c 2009-05-10 11:10:08 UTC (rev 9820)
@@ -217,8 +217,8 @@
Char* gdb_path = GDB_PATH;
// Ensure the message goes to stdout
- VG_(clo_log_fd) = 1;
- vg_assert( !VG_(logging_to_socket) );
+ VG_(log_output_sink).fd = 1;
+ VG_(log_output_sink).is_socket = False;
/* 'usage1' expects one char* argument */
VG_(printf)(usage1, gdb_path);
@@ -275,7 +275,8 @@
vg_assert(str);
// Nb: the version string goes to stdout.
- if VG_XACT_CLO(str, "--version", VG_(clo_log_fd), 1) {
+ if VG_XACT_CLO(str, "--version", VG_(log_output_sink).fd, 1) {
+ VG_(log_output_sink).is_socket = False;
VG_(printf)("valgrind-" VERSION "\n");
VG_(exit)(0);
}
@@ -297,26 +298,59 @@
}
/* The main processing for command line options. See comments above
- on early_process_cmd_line_options.
+ on early_process_cmd_line_options.
+
+ Comments on how the logging options are handled:
+
+ User can specify:
+ --log-fd= for a fd to write to (default setting, fd = 2)
+ --log-file= for a file name to write to
+ --log-socket= for a socket to write to
+
+ As a result of examining these and doing relevant socket/file
+ opening, a final fd is established. This is stored in
+ VG_(log_output_sink) in m_libcprint. Also, if --log-file=STR was
+ specified, then STR, after expansion of %p and %q templates within
+ it, is stored in VG_(clo_log_fname_expanded), in m_options, just in
+ case anybody wants to know what it is.
+
+ When printing, VG_(log_output_sink) is consulted to find the
+ fd to send output to.
+
+ Exactly analogous actions are undertaken for the XML output
+ channel, with the one difference that the default fd is -1, meaning
+ the channel is disabled by default.
*/
-static Bool main_process_cmd_line_options( const HChar* toolname )
+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;
+ Int i, tmp_log_fd, tmp_xml_fd;
Int toolname_len = VG_(strlen)(toolname);
Char* tmp_str; // Used in a couple of places.
enum {
VgLogTo_Fd,
VgLogTo_File,
VgLogTo_Socket
- } log_to = VgLogTo_Fd; // Where is logging output to be sent?
+ } log_to = VgLogTo_Fd, // Where is logging output to be sent?
+ xml_to = VgLogTo_Fd; // Where is XML output to be sent?
- /* log to stderr by default, but usage message goes to stdout */
+ /* Temporarily holds the string STR specified with
+ --{log,xml}-{name,socket}=STR. 'fs' stands for
+ file-or-socket. */
+ Char* log_fsname_unexpanded = NULL;
+ Char* xml_fsname_unexpanded = NULL;
+
+ /* Log to stderr by default, but usage message goes to stdout. XML
+ output is initially disabled. */
tmp_log_fd = 2;
-
+ tmp_xml_fd = -1;
+
/* Check for sane path in ./configure --prefix=... */
if (VG_LIBDIR[0] != '/')
VG_(err_config_error)("Please use absolute paths in "
@@ -450,16 +484,26 @@
else if VG_INT_CLO(arg, "--log-fd", tmp_log_fd) {
log_to = VgLogTo_Fd;
- VG_(clo_log_name) = NULL;
+ log_fsname_unexpanded = NULL;
}
+ else if VG_INT_CLO(arg, "--xml-fd", tmp_xml_fd) {
+ xml_to = VgLogTo_Fd;
+ xml_fsname_unexpanded = NULL;
+ }
- else if VG_STR_CLO(arg, "--log-file", VG_(clo_log_name)) {
+ else if VG_STR_CLO(arg, "--log-file", log_fsname_unexpanded) {
log_to = VgLogTo_File;
}
-
- else if VG_STR_CLO(arg, "--log-socket", VG_(clo_log_name)) {
+ else if VG_STR_CLO(arg, "--xml-file", xml_fsname_unexpanded) {
+ xml_to = VgLogTo_File;
+ }
+
+ else if VG_STR_CLO(arg, "--log-socket", log_fsname_unexpanded) {
log_to = VgLogTo_Socket;
}
+ else if VG_STR_CLO(arg, "--xml-socket", xml_fsname_unexpanded) {
+ xml_to = VgLogTo_Socket;
+ }
else if VG_STR_CLO(arg, "--xml-user-comment",
VG_(clo_xml_user_comment)) {}
@@ -554,6 +598,16 @@
VG_(err_bad_option)("--gen-suppressions=");
}
+ /* If XML output is requested, check that the tool actually
+ supports it. */
+ if (VG_(clo_xml) && !VG_(needs).xml_output) {
+ VG_(clo_xml) = False;
+ VG_(message)(Vg_UserMsg,
+ "%s does not support XML output.\n", VG_(details).name);
+ VG_(err_bad_option)("--xml=yes");
+ /*NOTREACHED*/
+ }
+
/* If we've been asked to emit XML, mash around various other
options so as to constrain the output somewhat, and to remove
any need for user input during the run. */
@@ -588,34 +642,44 @@
the terminal any problems to do with processing command line
opts.)
- So set up logging now. After this is done, VG_(clo_log_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 set up logging now. After this is done, VG_(log_output_sink)
+ and (if relevant) VG_(xml_output_sink) 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. */
- vg_assert(VG_(clo_log_fd) == 2 /* stderr */);
- vg_assert(VG_(logging_to_socket) == False);
+ vg_assert(VG_(log_output_sink).fd == 2 /* stderr */);
+ vg_assert(VG_(log_output_sink).is_socket == False);
+ vg_assert(VG_(clo_log_fname_expanded) == NULL);
+ vg_assert(VG_(xml_output_sink).fd == -1 /* disabled */);
+ vg_assert(VG_(xml_output_sink).is_socket == False);
+ vg_assert(VG_(clo_xml_fname_expanded) == NULL);
+
+ /* --- set up the normal text output channel --- */
+
switch (log_to) {
case VgLogTo_Fd:
- vg_assert(VG_(clo_log_name) == NULL);
+ vg_assert(log_fsname_unexpanded == NULL);
break;
case VgLogTo_File: {
Char* logfilename;
- vg_assert(VG_(clo_log_name) != NULL);
- vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
+ 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", VG_(clo_log_name));
+ 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 (!sres.isError) {
tmp_log_fd = sres.res;
+ VG_(clo_log_fname_expanded) = logfilename;
} else {
VG_(message)(Vg_UserMsg,
"Can't create log file '%s' (%s); giving up!\n",
@@ -624,19 +688,19 @@
"--log-file=<file> (didn't work out for some reason.)");
/*NOTREACHED*/
}
- break; /* switch (VG_(clo_log_to)) */
+ break;
}
case VgLogTo_Socket: {
- vg_assert(VG_(clo_log_name) != NULL);
- vg_assert(VG_(strlen)(VG_(clo_log_name)) <= 900); /* paranoia */
- tmp_log_fd = VG_(connect_via_socket)( VG_(clo_log_name) );
+ vg_assert(log_fsname_unexpanded != NULL);
+ vg_assert(VG_(strlen)(log_fsname_unexpanded) <= 900); /* paranoia */
+ tmp_log_fd = VG_(connect_via_socket)( log_fsname_unexpanded );
if (tmp_log_fd == -1) {
VG_(message)(Vg_UserMsg,
"Invalid --log-socket=ipaddr or "
"--log-socket=ipaddr:port spec\n");
VG_(message)(Vg_UserMsg,
- "of '%s'; giving up!\n", VG_(clo_log_name) );
+ "of '%s'; giving up!\n", log_fsname_unexpanded );
VG_(err_bad_option)(
"--log-socket=");
/*NOTREACHED*/
@@ -644,62 +708,152 @@
if (tmp_log_fd == -2) {
VG_(message)(Vg_UserMsg,
"valgrind: failed to connect to logging server '%s'.\n",
- VG_(clo_log_name) );
+ log_fsname_unexpanded );
VG_(message)(Vg_UserMsg,
"Log messages will sent to stderr instead.\n" );
VG_(message)(Vg_UserMsg,
"\n" );
/* We don't change anything here. */
- vg_assert(VG_(clo_log_fd) == 2);
+ vg_assert(VG_(log_output_sink).fd == 2);
tmp_log_fd = 2;
} else {
vg_assert(tmp_log_fd > 0);
- VG_(logging_to_socket) = True;
+ VG_(log_output_sink).is_socket = True;
}
break;
}
}
+ /* --- set up the XML output channel --- */
- /* Check that the requested tool actually supports XML output. */
- if (VG_(clo_xml) && !VG_(needs).xml_output) {
- VG_(clo_xml) = False;
- VG_(message)(Vg_UserMsg,
- "%s does not support XML output.\n", VG_(details).name);
- VG_(err_bad_option)("--xml=yes");
- /*NOTREACHED*/
+ switch (xml_to) {
+
+ case VgLogTo_Fd:
+ vg_assert(xml_fsname_unexpanded == NULL);
+ 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 (!sres.isError) {
+ tmp_xml_fd = sres.res;
+ 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)(sres.err));
+ VG_(err_bad_option)(
+ "--xml-file=<file> (didn't work out for some reason.)");
+ /*NOTREACHED*/
+ }
+ break;
+ }
+
+ case VgLogTo_Socket: {
+ vg_assert(xml_fsname_unexpanded != NULL);
+ vg_assert(VG_(strlen)(xml_fsname_unexpanded) <= 900); /* paranoia */
+ tmp_xml_fd = VG_(connect_via_socket)( xml_fsname_unexpanded );
+ if (tmp_xml_fd == -1) {
+ VG_(message)(Vg_UserMsg,
+ "Invalid --xml-socket=ipaddr or "
+ "--xml-socket=ipaddr:port spec\n");
+ VG_(message)(Vg_UserMsg,
+ "of '%s'; giving up!\n", xml_fsname_unexpanded );
+ VG_(err_bad_option)(
+ "--xml-socket=");
+ /*NOTREACHED*/
+ }
+ if (tmp_xml_fd == -2) {
+ VG_(message)(Vg_UserMsg,
+ "valgrind: failed to connect to XML logging server '%s'.\n",
+ xml_fsname_unexpanded );
+ VG_(message)(Vg_UserMsg,
+ "XML output will sent to stderr instead.\n" );
+ VG_(message)(Vg_UserMsg,
+ "\n" );
+ /* We don't change anything here. */
+ vg_assert(VG_(xml_output_sink).fd == 2);
+ tmp_xml_fd = 2;
+ } else {
+ vg_assert(tmp_xml_fd > 0);
+ VG_(xml_output_sink).is_socket = True;
+ }
+ break;
+ }
}
+ // 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.
+ // 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_(clo_log_fd) = 2; // stderr
+ 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_(clo_log_fd) = tmp_log_fd;
- VG_(fcntl)(VG_(clo_log_fd), VKI_F_SETFD, VKI_FD_CLOEXEC);
+ VG_(log_output_sink).fd = tmp_log_fd;
+ VG_(fcntl)(VG_(log_output_sink).fd, VKI_F_SETFD, VKI_FD_CLOEXEC);
}
} 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.
- VG_(clo_log_fd) = tmp_log_fd;
+ VG_(log_output_sink).fd = -1;
+ VG_(log_output_sink).is_socket = False;
}
+ // 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);
+ }
+ } 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.
+ VG_(xml_output_sink).fd = -1;
+ VG_(xml_output_sink).is_socket = False;
+ }
+
+ // Suppressions related stuff
+
if (VG_(clo_n_suppressions) < VG_CLO_MAX_SFILES-1 &&
(VG_(needs).core_errors || VG_(needs).tool_errors)) {
/* If we haven't reached the max number of suppressions, load
the default one. */
static const Char default_supp[] = "default.supp";
Int len = VG_(strlen)(VG_(libdir)) + 1 + sizeof(default_supp);
- Char *buf = VG_(arena_malloc)(VG_AR_CORE, "main.mpclo.2", len);
+ Char *buf = VG_(arena_malloc)(VG_AR_CORE, "main.mpclo.3", len);
VG_(sprintf)(buf, "%s/%s", VG_(libdir), default_supp);
VG_(clo_suppressions)[VG_(clo_n_suppressions)] = buf;
VG_(clo_n_suppressions)++;
}
- return (log_to == VgLogTo_Fd);
+ *logging_to_fd = log_to == VgLogTo_Fd || log_to == VgLogTo_Socket;
}
// Write the name and value of log file qualifiers to the xml file.
@@ -753,7 +907,9 @@
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)
+static void print_preamble ( Bool logging_to_fd,
+ Char* xml_fname_unexpanded,
+ const HChar* toolname )
{
HChar* xpre = VG_(clo_xml) ? " <line>" : "";
HChar* xpost = VG_(clo_xml) ? "</line>" : "";
@@ -838,8 +994,8 @@
VG_(message)(Vg_UserMsg, "<pid>%d</pid>\n", VG_(getpid)());
VG_(message)(Vg_UserMsg, "<ppid>%d</ppid>\n", VG_(getppid)());
VG_(message_no_f_c)(Vg_UserMsg, "<tool>%t</tool>\n", toolname);
- if (VG_(clo_log_name))
- print_file_vars(VG_(clo_log_name));
+ if (xml_fname_unexpanded)
+ print_file_vars(xml_fname_unexpanded);
if (VG_(clo_xml_user_comment)) {
/* Note: the user comment itself is XML and is therefore to
be passed through verbatim (%s) rather than escaped
@@ -1140,8 +1296,9 @@
HChar* toolname = "memcheck"; // default to Memcheck
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;
- Bool logging_to_fd;
struct vki_rlimit zero = { 0, 0 };
XArray* addr2dihandle = NULL;
@@ -1580,7 +1737,8 @@
VG_(debugLog)(1, "main",
"(main_) Process Valgrind's command line options, "
"setup logging\n");
- logging_to_fd = main_process_cmd_line_options(toolname);
+ main_process_cmd_line_options ( &logging_to_fd, &xml_fname_unexpanded,
+ toolname );
//--------------------------------------------------------------
// Zeroise the millisecond counter by doing a first read of it.
@@ -1591,12 +1749,12 @@
//--------------------------------------------------------------
// Print the preamble
// 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]
+ // p: main_process_cmd_line_options()
+ // [for VG_(clo_verbosity), VG_(clo_xml),
+ // logging_to_fd, xml_fname_unexpanded]
//--------------------------------------------------------------
VG_(debugLog)(1, "main", "Print the preamble...\n");
- print_preamble(logging_to_fd, toolname);
+ print_preamble(logging_to_fd, xml_fname_unexpanded, toolname);
VG_(debugLog)(1, "main", "...finished the preamble\n");
//--------------------------------------------------------------
Modified: branches/MESSAGING_TIDYUP/coregrind/m_options.c
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/m_options.c 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/m_options.c 2009-05-10 11:10:08 UTC (rev 9820)
@@ -56,8 +56,8 @@
Bool VG_(clo_demangle) = True;
Bool VG_(clo_trace_children) = False;
Bool VG_(clo_child_silent_after_fork) = False;
-Int VG_(clo_log_fd) = 2; /* must be signed, as -1 is possible. */
-Char* VG_(clo_log_name) = NULL;
+Char* VG_(clo_log_fname_expanded) = NULL;
+Char* VG_(clo_xml_fname_expanded) = NULL;
Bool VG_(clo_time_stamp) = False;
Int VG_(clo_input_fd) = 0; /* stdin */
Int VG_(clo_n_suppressions) = 0;
@@ -98,8 +98,8 @@
static void revert_to_stderr ( void )
{
- vg_assert( !VG_(logging_to_socket) );
- VG_(clo_log_fd) = 2; /* stderr */
+ VG_(log_output_sink).fd = 2; /* stderr */
+ VG_(log_output_sink).is_socket = False;
}
__attribute__((noreturn))
Modified: branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-generic.c
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-generic.c 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-generic.c 2009-05-10 11:10:08 UTC (rev 9820)
@@ -1125,8 +1125,8 @@
if (fd < 0 || fd >= VG_(fd_hard_limit))
allowed = False;
- /* hijacking the logging fd is never allowed */
- if (fd == VG_(clo_log_fd))
+ /* hijacking the output fds is never allowed */
+ if (fd == VG_(log_output_sink).fd || fd == VG_(xml_output_sink).fd)
allowed = False;
/* if creating a new fd (rather than using an existing one), the
@@ -1157,9 +1157,13 @@
VG_(message)(Vg_UserMsg,
"Warning: invalid file descriptor %d in syscall %s()\n",
fd, syscallname);
- if (fd == VG_(clo_log_fd))
+ if (fd == VG_(log_output_sink).fd)
VG_(message)(Vg_UserMsg,
" Use --log-fd=<number> to select an alternative log fd.\n");
+ if (fd == VG_(xml_output_sink).fd)
+ VG_(message)(Vg_UserMsg,
+ " Use --xml-fd=<number> to select an alternative XML "
+ "output fd.\n");
if (VG_(clo_verbosity) > 1) {
VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
}
@@ -2792,11 +2796,15 @@
VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
/* If --child-silent-after-fork=yes was specified, set the
- logging file descriptor to an 'impossible' value. This is
+ output file descriptors to 'impossible' values. This is
noticed by send_bytes_to_logging_sink in m_libcprint.c, which
- duly stops writing any further logging output. */
- if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork))
- VG_(clo_log_fd) = -1;
+ duly stops writing any further output. */
+ if (VG_(clo_child_silent_after_fork)) {
+ if (!VG_(log_output_sink).is_socket)
+ VG_(log_output_sink).fd = -1;
+ if (!VG_(xml_output_sink).is_socket)
+ VG_(xml_output_sink).fd = -1;
+ }
}
else
if (SUCCESS && RES > 0) {
Modified: branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-linux.c
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-linux.c 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/m_syswrap/syswrap-linux.c 2009-05-10 11:10:08 UTC (rev 9820)
@@ -339,11 +339,15 @@
VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
/* If --child-silent-after-fork=yes was specified, set the
- logging file descriptor to an 'impossible' value. This is
+ output file descriptors to 'impossible' values. This is
noticed by send_bytes_to_logging_sink in m_libcprint.c, which
- duly stops writing any further logging output. */
- if (!VG_(logging_to_socket) && VG_(clo_child_silent_after_fork))
- VG_(clo_log_fd) = -1;
+ duly stops writing any further output. */
+ if (VG_(clo_child_silent_after_fork)) {
+ if (!VG_(log_output_sink).is_socket)
+ VG_(log_output_sink).fd = -1;
+ if (!VG_(xml_output_sink).is_socket)
+ VG_(xml_output_sink).fd = -1;
+ }
}
else
if (!res.isError && res.res > 0) {
Modified: branches/MESSAGING_TIDYUP/coregrind/pub_core_libcprint.h
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/pub_core_libcprint.h 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/pub_core_libcprint.h 2009-05-10 11:10:08 UTC (rev 9820)
@@ -38,9 +38,15 @@
#include "pub_tool_libcprint.h"
-/* Tell the logging mechanism whether we are logging to a file
- descriptor or a socket descriptor. */
-extern Bool VG_(logging_to_socket);
+/* An output file descriptor wrapped up with a Bool indicating whether
+ or not the fd is a socket. */
+typedef
+ struct { Int fd; Bool is_socket; }
+ OutputSink;
+
+/* And the destinations for normal and XML output. */
+extern OutputSink VG_(log_output_sink);
+extern OutputSink VG_(xml_output_sink);
/* Get the elapsed wallclock time since startup into buf, which must
16 chars long. This is unchecked. It also relies on the
Modified: branches/MESSAGING_TIDYUP/coregrind/pub_core_options.h
===================================================================
--- branches/MESSAGING_TIDYUP/coregrind/pub_core_options.h 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/coregrind/pub_core_options.h 2009-05-10 11:10:08 UTC (rev 9820)
@@ -65,31 +65,15 @@
intermingled with the parent's output. This is especially
problematic when VG_(clo_xml) is True. Setting
VG_(clo_child_silent_after_fork) causes children to fall silent
- after fork() calls. */
+ after fork() calls. Although note they become un-silent again
+ after the subsequent exec(). */
extern Bool VG_(clo_child_silent_after_fork);
-/* Where logging output is to be sent to.
+/* If the user specified --log-file=STR and/or --xml-file=STR, these
+ hold STR after expansion of the %p and %q templates. */
+extern Char* VG_(clo_log_fname_expanded);
+extern Char* VG_(clo_xml_fname_expanded);
- With --log-fd (and by default), clo_log_fd holds the file id, and is
- taken from the command line. (fd 2, stderr, is the default.)
- clo_log_name is irrelevant.
-
- With --log-file, clo_log_name holds the log-file name, and is taken from
- the command line (and possibly has process ID/env var contents in it, if
- the %p or %q format specifiers are used). clo_log_fd is then made to
- hold the relevant file id, by opening clo_log_name (concatenated with the
- process ID) for writing.
-
- With --log-socket, clo_log_name holds the hostname:portnumber pair,
- and is taken from the command line. clo_log_fd is then made to hold
- the relevant file handle, by opening a connection to that
- hostname:portnumber pair.
-
- Global default is to set log_to == VgLogTo_Fd and log_fd == 2
- (stderr). */
-extern Int VG_(clo_log_fd);
-extern Char* VG_(clo_log_name);
-
/* Add timestamps to log messages? default: NO */
extern Bool VG_(clo_time_stamp);
Modified: branches/MESSAGING_TIDYUP/include/pub_tool_libcprint.h
===================================================================
--- branches/MESSAGING_TIDYUP/include/pub_tool_libcprint.h 2009-05-10 11:08:10 UTC (rev 9819)
+++ branches/MESSAGING_TIDYUP/include/pub_tool_libcprint.h 2009-05-10 11:10:08 UTC (rev 9820)
@@ -50,22 +50,47 @@
------------------------------------------------------------------ */
/* Note that they all output to the file descriptor given by the
- * --log-fd/--log-file/--log-socket argument, which defaults to 2 (stderr).
- * Hence no need for VG_(fprintf)().
- */
-extern UInt VG_(printf) ( const HChar *format, ... ) PRINTF_CHECK(1, 2);
-extern UInt VG_(vprintf) ( const HChar *format, va_list vargs ) PRINTF_CHECK(1, 0);
-extern UInt VG_(sprintf) ( Char* buf, const HChar* format, ... ) PRINTF_CHECK(2, 3);
-extern UInt VG_(vsprintf) ( Char* buf, const HChar* format, va_list vargs ) PRINTF_CHECK(2, 0);
+ --log-fd/--log-file/--log-socket argument, which defaults to 2
+ (stderr). Hence no need for VG_(fprintf)().
+*/
+extern UInt VG_(printf) ( const HChar *format, ... )
+ PRINTF_CHECK(1, 2);
+
+extern UInt VG_(vprintf) ( const HChar *format, va_list vargs )
+ PRINTF_CHECK(1, 0);
+
+extern UInt VG_(sprintf) ( Char* buf, const HChar* format, ... )
+ PRINTF_CHECK(2, 3);
+
+extern UInt VG_(vsprintf) ( Char* buf, const HChar* format, va_list vargs )
+ PRINTF_CHECK(2, 0);
+
extern UInt VG_(snprintf) ( Char* buf, Int size,
- const HChar *format, ... ) PRINTF_CHECK(3, 4);
+ const HChar *format, ... )
+ PRINTF_CHECK(3, 4);
+
extern UInt VG_(vsnprintf)( Char* buf, Int size,
- const HChar *format, va_list vargs ) PRINTF_CHECK(3, 0);
+ const HChar *format, va_list vargs )
+ PRINTF_CHECK(3, 0);
+/* These are the same as the non "_xml" versions above, except the
+ output goes on the selected XML output channel instead of the
+ normal one.
+*/
+extern UInt VG_(printf_xml) ( const HChar *format, ... )
+ PRINTF_CHECK(1, 2);
+
+extern UInt VG_(vprintf_xml) ( const HChar *format, va_list vargs )
+ PRINTF_CHECK(1, 0);
+
+extern UInt VG_(printf_xml_no_f_c) ( const HChar *format, ... );
+
+
// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
// Right justifies in 'buf'.
extern void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, char buf[]);
+
/* ---------------------------------------------------------------------
Messages for the user
------------------------------------------------------------------ */
|