Support for truncate/append on log files

Summary:
Presently, if a log file already exists, lldb simply starts overwriting bits of it, without
truncating or anything. This patch makes it use eFileOptionFileTruncate by default. It also adds
an --append option, which will append to the file without truncating. A test is included.

Reviewers: clayborg

Subscribers: lldb-commits

Differential Revision: http://reviews.llvm.org/D8450

llvm-svn: 232801
This commit is contained in:
Pavel Labath
2015-03-20 09:43:20 +00:00
parent 0068cb2499
commit 8ac06996bf
6 changed files with 72 additions and 2 deletions

View File

@@ -47,6 +47,7 @@
#define LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD (1u << 5)
#define LLDB_LOG_OPTION_PREPEND_THREAD_NAME (1U << 6)
#define LLDB_LOG_OPTION_BACKTRACE (1U << 7)
#define LLDB_LOG_OPTION_APPEND (1U << 8)
//----------------------------------------------------------------------
// Logging Functions

View File

@@ -37,6 +37,10 @@ public:
StreamFile (const char *path);
StreamFile (const char *path,
uint32_t options,
uint32_t permissions = lldb::eFilePermissionsFileDefault);
StreamFile (FILE *fh, bool transfer_ownership);
virtual

View File

@@ -146,6 +146,7 @@ public:
case 'p': log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
case 'n': log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; break;
case 'S': log_options |= LLDB_LOG_OPTION_BACKTRACE; break;
case 'a': log_options |= LLDB_LOG_OPTION_APPEND; break;
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
@@ -223,6 +224,7 @@ CommandObjectLogEnable::CommandOptions::g_option_table[] =
{ LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." },
{ LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." },
{ LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
{ LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Append to the log file instead of overwriting." },
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};

View File

@@ -1331,7 +1331,12 @@ Debugger::EnableLog (const char *channel, const char **categories, const char *l
log_stream_sp = pos->second.lock();
if (!log_stream_sp)
{
log_stream_sp.reset (new StreamFile (log_file));
uint32_t options = File::eOpenOptionWrite | File::eOpenOptionCanCreate
| File::eOpenOptionCloseOnExec | File::eOpenOptionAppend;
if (! (log_options & LLDB_LOG_OPTION_APPEND))
options |= File::eOpenOptionTruncate;
log_stream_sp.reset (new StreamFile (log_file, options));
m_log_streams[log_file] = log_stream_sp;
}
}

View File

@@ -54,6 +54,13 @@ StreamFile::StreamFile (const char *path) :
{
}
StreamFile::StreamFile (const char *path,
uint32_t options,
uint32_t permissions) :
Stream(),
m_file(path, options, permissions)
{
}
StreamFile::~StreamFile()
{

View File

@@ -2,7 +2,7 @@
Test lldb logging. This test just makes sure logging doesn't crash, and produces some output.
"""
import os, time
import os, time, string
import unittest2
import lldb
from lldbtest import *
@@ -10,6 +10,15 @@ from lldbtest import *
class LogTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
append_log_file = "lldb-commands-log-append.txt"
truncate_log_file = "lldb-commands-log-truncate.txt"
@classmethod
def classCleanup(cls):
"""Cleanup the test byproducts."""
cls.RemoveTempFile(cls.truncate_log_file)
cls.RemoveTempFile(cls.append_log_file)
@unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
@dsym_test
@@ -56,6 +65,48 @@ class LogTestCase(TestBase):
self.assertTrue(log_lines > 0, "Something was written to the log file.")
# Check that lldb truncates its log files
def test_log_truncate (self):
if (os.path.exists (self.truncate_log_file)):
os.remove (self.truncate_log_file)
# put something in our log file
with open(self.truncate_log_file, "w") as f:
for i in range(1, 1000):
f.write("bacon\n")
self.runCmd ("log enable -t -f '%s' lldb commands" % (self.truncate_log_file))
self.runCmd ("help log")
self.runCmd ("log disable lldb")
self.assertTrue (os.path.isfile (self.truncate_log_file))
with open(self.truncate_log_file, "r") as f:
contents = f.read ()
# check that it got removed
self.assertTrue(string.find(contents, "bacon") == -1)
# Check that lldb can append to a log file
def test_log_append (self):
if (os.path.exists (self.append_log_file)):
os.remove (self.append_log_file)
# put something in our log file
with open(self.append_log_file, "w") as f:
f.write("bacon\n")
self.runCmd ("log enable -t -a -f '%s' lldb commands" % (self.append_log_file))
self.runCmd ("help log")
self.runCmd ("log disable lldb")
self.assertTrue (os.path.isfile (self.append_log_file))
with open(self.append_log_file, "r") as f:
contents = f.read ()
# check that it is still there
self.assertTrue(string.find(contents, "bacon") == 0)
if __name__ == '__main__':
import atexit
lldb.SBDebugger.Initialize()