diff --git a/doc/release-notes.md b/doc/release-notes.md index 1956746c3aaf9..eee7c183011ef 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -150,6 +150,12 @@ E.g. `logging "[\"all\"]" "[\"http\"]""` Details about each new command can be found below. +Changed command-line options +----------------------------- + +- `-debuglogfile=` can be used to specify an alternative debug logging file. This can be an absolute path or a path relative to the data directory + + *version* Change log ============== diff --git a/src/init.cpp b/src/init.cpp index 68a8992e8f2d8..e99fee0a376c5 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -383,6 +383,7 @@ std::string HelpMessage(HelpMessageMode mode) #endif } strUsage += HelpMessageOpt("-datadir=", _("Specify data directory")); + strUsage += HelpMessageOpt("-debuglogfile=", strprintf(_("Specify location of debug log file: this can be an absolute path or a path relative to the data directory (default: %s)"), DEFAULT_DEBUGLOGFILE)); strUsage += HelpMessageOpt("-dbcache=", strprintf(_("Set database cache size in megabytes (%d to %d, default: %d)"), nMinDbCache, nMaxDbCache, nDefaultDbCache)); strUsage += HelpMessageOpt("-loadblock=", _("Imports blocks from external blk000??.dat file") + " " + _("on startup")); strUsage += HelpMessageOpt("-maxreorg=", strprintf(_("Set the Maximum reorg depth (default: %u)"), DEFAULT_MAX_REORG_DEPTH)); @@ -1063,8 +1064,9 @@ bool AppInit2() #endif if (GetBoolArg("-shrinkdebugfile", logCategories != BCLog::NONE)) ShrinkDebugFile(); - if (fPrintToDebugLog) - OpenDebugLog(); + if (fPrintToDebugLog && !OpenDebugLog()) { + return UIError(strprintf("Could not open debug log file %s", GetDebugLogPath().string())); + } #ifdef ENABLE_WALLET LogPrintf("Using BerkeleyDB version %s\n", DbEnv::version(0, 0, 0)); #endif diff --git a/src/util.cpp b/src/util.cpp index 958bf072a951e..452ef33ca154a 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -102,6 +102,9 @@ bool fSucessfullyLoaded = false; std::vector obfuScationDenominations; std::string strBudgetMode = ""; +const char * const DEFAULT_DEBUGLOGFILE = "debug.log"; +namespace fs = boost::filesystem; + std::map mapArgs; std::map > mapMultiArgs; bool fPrintToConsole = false; @@ -203,17 +206,29 @@ static void DebugPrintInit() vMsgsBeforeOpenLog = new std::list; } -void OpenDebugLog() +fs::path GetDebugLogPath() +{ + fs::path logfile(GetArg("-debuglogfile", DEFAULT_DEBUGLOGFILE)); + if (logfile.is_absolute()) { + return logfile; + } else { + return GetDataDir() / logfile; + } +} + +bool OpenDebugLog() { boost::call_once(&DebugPrintInit, debugPrintInitFlag); boost::mutex::scoped_lock scoped_lock(*mutexDebugLog); assert(fileout == nullptr); assert(vMsgsBeforeOpenLog); - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + boost::filesystem::path pathDebug = GetDebugLogPath(); + fileout = fopen(pathDebug.string().c_str(), "a"); - if (fileout) setbuf(fileout, nullptr); // unbuffered + if (!fileout) return false; + setbuf(fileout, nullptr); // unbuffered // dump buffered messages from before we opened the log while (!vMsgsBeforeOpenLog->empty()) { FileWriteStr(vMsgsBeforeOpenLog->front(), fileout); @@ -222,6 +237,7 @@ void OpenDebugLog() delete vMsgsBeforeOpenLog; vMsgsBeforeOpenLog = nullptr; + return true; } struct CLogCategoryDesc @@ -357,7 +373,7 @@ int LogPrintStr(const std::string& str) // reopen the log file, if requested if (fReopenDebugLog) { fReopenDebugLog = false; - boost::filesystem::path pathDebug = GetDataDir() / "debug.log"; + boost::filesystem::path pathDebug = GetDebugLogPath(); if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL) setbuf(fileout, NULL); // unbuffered } @@ -497,7 +513,6 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread) boost::filesystem::path GetDefaultDataDir() { - namespace fs = boost::filesystem; // Windows < Vista: C:\Documents and Settings\Username\Application Data\PIVX // Windows >= Vista: C:\Users\Username\AppData\Roaming\PIVX // Mac: ~/Library/Application Support/PIVX @@ -524,14 +539,12 @@ boost::filesystem::path GetDefaultDataDir() #endif } -static boost::filesystem::path pathCached; -static boost::filesystem::path pathCachedNetSpecific; +static fs::path pathCached; +static fs::path pathCachedNetSpecific; static RecursiveMutex csPathCached; -const boost::filesystem::path& GetDataDir(bool fNetSpecific) +const fs::path& GetDataDir(bool fNetSpecific) { - namespace fs = boost::filesystem; - LOCK(csPathCached); fs::path& path = fNetSpecific ? pathCachedNetSpecific : pathCached; @@ -755,7 +768,7 @@ void AllocateFileRange(FILE* file, unsigned int offset, unsigned int length) void ShrinkDebugFile() { // Scroll debug.log if it's getting too big - boost::filesystem::path pathLog = GetDataDir() / "debug.log"; + boost::filesystem::path pathLog = GetDebugLogPath(); FILE* file = fopen(pathLog.string().c_str(), "r"); if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000) { // Restart the file with some of the end @@ -776,8 +789,6 @@ void ShrinkDebugFile() #ifdef WIN32 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate) { - namespace fs = boost::filesystem; - char pszPath[MAX_PATH] = ""; if (SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate)) { diff --git a/src/util.h b/src/util.h index 6733d634595a1..e5bb1d30b5cbb 100644 --- a/src/util.h +++ b/src/util.h @@ -32,6 +32,8 @@ #include #include // for boost::thread_interrupted +extern const char * const DEFAULT_DEBUGLOGFILE; + //PIVX only features extern bool fMasterNode; @@ -161,7 +163,8 @@ void ReadConfigFile(std::map& mapSettingsRet, std::map boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif boost::filesystem::path GetTempPath(); -void OpenDebugLog(); +boost::filesystem::path GetDebugLogPath(); +bool OpenDebugLog(); void ShrinkDebugFile(); void runCommand(std::string strCommand); diff --git a/test/functional/feature_logging.py b/test/functional/feature_logging.py new file mode 100755 index 0000000000000..70299b374a525 --- /dev/null +++ b/test/functional/feature_logging.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# Copyright (c) 2017 The Bitcoin Core developers +# Copyright (c) 20200 The PIVX Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +"""Test debug logging.""" + +import os + +from test_framework.test_framework import PivxTestFramework + +class LoggingTest(PivxTestFramework): + def set_test_params(self): + self.num_nodes = 1 + self.setup_clean_chain = True + + def run_test(self): + # test default log file name + assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "debug.log")) + self.log.info("Default filename ok") + + # test alternative log file name in datadir + self.restart_node(0, ["-debuglogfile=foo.log"]) + assert os.path.isfile(os.path.join(self.nodes[0].datadir, "regtest", "foo.log")) + self.log.info("Alternative filename ok") + + # test alternative log file name outside datadir + tempname = os.path.join(self.options.tmpdir, "foo.log") + self.restart_node(0, ["-debuglogfile=%s" % tempname]) + assert os.path.isfile(tempname) + self.log.info("Alternative filename outside datadir ok") + + # check that invalid log (relative) will cause error + invdir = os.path.join(self.nodes[0].datadir, "regtest", "foo") + invalidname = os.path.join("foo", "foo.log") + self.stop_node(0) + self.assert_start_raises_init_error(0, ["-debuglogfile=%s" % (invalidname)], + "Error: Could not open debug log file") + assert not os.path.isfile(os.path.join(invdir, "foo.log")) + self.log.info("Invalid relative filename throws") + + # check that a previously invalid log (relative) works after path exists + os.mkdir(invdir) + self.start_node(0, ["-debuglogfile=%s" % (invalidname)]) + assert os.path.isfile(os.path.join(invdir, "foo.log")) + self.log.info("Relative filename ok when path exists") + + # check that invalid log (absolute) will cause error + self.stop_node(0) + invdir = os.path.join(self.options.tmpdir, "foo") + invalidname = os.path.join(invdir, "foo.log") + self.assert_start_raises_init_error(0, ["-debuglogfile=%s" % invalidname], + "Error: Could not open debug log file") + assert not os.path.isfile(os.path.join(invdir, "foo.log")) + self.log.info("Invalid absolute filename throws") + + # check that a previously invalid log (relative) works after path exists + os.mkdir(invdir) + self.start_node(0, ["-debuglogfile=%s" % (invalidname)]) + assert os.path.isfile(os.path.join(invdir, "foo.log")) + self.log.info("Absolute filename ok when path exists") + + +if __name__ == '__main__': + LoggingTest().main() \ No newline at end of file diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 94ac0066279ca..75c6ec399bad9 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -66,6 +66,7 @@ 'wallet_abandonconflict.py', # ~ 212 sec 'wallet_hd.py', # ~ 210 sec 'wallet_zerocoin_publicspends.py', # ~ 202 sec + 'feature_logging.py', # ~ 200 sec 'rpc_rawtransaction.py', # ~ 193 sec 'wallet_zapwallettxes.py', # ~ 180 sec 'wallet_keypool_topup.py', # ~ 174 sec @@ -153,6 +154,7 @@ LEGACY_SKIP_TESTS = [ # These tests are not run when the flag --legacywallet is used 'feature_help.py', + 'feature_logging.py', 'feature_reindex.py', 'feature_proxy.py', 'feature_uacomment.py',