From 8ac06996bf6e602888692df1836eeec02966db16 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Fri, 20 Mar 2015 09:43:20 +0000 Subject: [PATCH] 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 --- lldb/include/lldb/Core/Log.h | 1 + lldb/include/lldb/Core/StreamFile.h | 4 +++ lldb/source/Commands/CommandObjectLog.cpp | 2 ++ lldb/source/Core/Debugger.cpp | 7 +++- lldb/source/Core/StreamFile.cpp | 7 ++++ lldb/test/logging/TestLogging.py | 53 ++++++++++++++++++++++++++++++- 6 files changed, 72 insertions(+), 2 deletions(-) diff --git a/lldb/include/lldb/Core/Log.h b/lldb/include/lldb/Core/Log.h index 119b29b..e63633b 100644 --- a/lldb/include/lldb/Core/Log.h +++ b/lldb/include/lldb/Core/Log.h @@ -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 diff --git a/lldb/include/lldb/Core/StreamFile.h b/lldb/include/lldb/Core/StreamFile.h index d032c0b..55bb361 100644 --- a/lldb/include/lldb/Core/StreamFile.h +++ b/lldb/include/lldb/Core/StreamFile.h @@ -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 diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp index d4334d5..dbc1a3e 100644 --- a/lldb/source/Commands/CommandObjectLog.cpp +++ b/lldb/source/Commands/CommandObjectLog.cpp @@ -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 } }; diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp index f93da0eb..7134d41 100644 --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -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; } } diff --git a/lldb/source/Core/StreamFile.cpp b/lldb/source/Core/StreamFile.cpp index 9f8dd62..8c9700c 100644 --- a/lldb/source/Core/StreamFile.cpp +++ b/lldb/source/Core/StreamFile.cpp @@ -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() { diff --git a/lldb/test/logging/TestLogging.py b/lldb/test/logging/TestLogging.py index 11d4321..aea077d 100644 --- a/lldb/test/logging/TestLogging.py +++ b/lldb/test/logging/TestLogging.py @@ -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() -- 2.7.4