Skip to content

Commit dda2613

Browse files
committed
Merge bitcoin/bitcoin#30929: log: Enforce trailing newline
fa2b7d8 Remove redundant unterminated-logprintf tidy check (MarcoFalke) bbbb2e4 log: Enforce trailing newline, Remove redundant m_started_new_line (MarcoFalke) Pull request description: There are many problems around missing a trailing newline while logging: * All log lines are currently terminated by a trailing newline. This means any runtime code trying to handle a "missing" newline is currently dead code. * Leaving a line unterminated is racy and can cause content corruption by mixing log lines from different sources. * It requires extra code like `m_started_new_line` to keep track of, which is annoying and pointless to maintain, because it is currently dead code, see bitcoin/bitcoin#30386 (comment). * It requires a standalone `unterminated-logprintf` clang-tidy plugin, which is unmaintained (no one updated it for the new log function names), probably harder to maintain than normal C++ code (because it requires clang AST matcher knowledge), brittle (it can fail to detect issues at any time, if it goes out-of-sync, or be explicitly disabled via `NOLINT`), and annoying for devs (it is slow and intricate to run locally and thus only effectively run on CI or via the CI scripts). Fix all issues by enforcing the trailing newline in logs directly in the code. Then remove all the other stuff. This refactor does not change behavior. ACKs for top commit: stickies-v: re-ACK fa2b7d8 achow101: ACK fa2b7d8 ryanofsky: Code review ACK fa2b7d8. Just comment and test cleanup since last review Tree-SHA512: 10ed420f6c2fdb0f491d6c880be8dd2e8beef628f510adebadf4c3849d9f5e28906519d5cbaeb295f4c7c1b07c4c88a9905b3cfe30fee3a2c91ac9fd24ae6755
2 parents e0ae9c1 + fa2b7d8 commit dda2613

9 files changed

+18
-238
lines changed

contrib/devtools/bitcoin-tidy/CMakeLists.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ find_program(CLANG_TIDY_EXE NAMES "clang-tidy-${LLVM_VERSION_MAJOR}" "clang-tidy
2525
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
2626
message(STATUS "Found clang-tidy: ${CLANG_TIDY_EXE}")
2727

28-
add_library(bitcoin-tidy MODULE bitcoin-tidy.cpp logprintf.cpp nontrivial-threadlocal.cpp)
28+
add_library(bitcoin-tidy MODULE bitcoin-tidy.cpp nontrivial-threadlocal.cpp)
2929
target_include_directories(bitcoin-tidy SYSTEM PRIVATE ${LLVM_INCLUDE_DIRS})
3030

3131
# Disable RTTI and exceptions as necessary
@@ -58,7 +58,7 @@ else()
5858
endif()
5959

6060
# Create a dummy library that runs clang-tidy tests as a side-effect of building
61-
add_library(bitcoin-tidy-tests OBJECT EXCLUDE_FROM_ALL example_logprintf.cpp example_nontrivial-threadlocal.cpp)
61+
add_library(bitcoin-tidy-tests OBJECT EXCLUDE_FROM_ALL example_nontrivial-threadlocal.cpp)
6262
add_dependencies(bitcoin-tidy-tests bitcoin-tidy)
6363

6464
set_target_properties(bitcoin-tidy-tests PROPERTIES CXX_CLANG_TIDY "${CLANG_TIDY_COMMAND}")

contrib/devtools/bitcoin-tidy/bitcoin-tidy.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include "logprintf.h"
65
#include "nontrivial-threadlocal.h"
76

87
#include <clang-tidy/ClangTidyModule.h>
@@ -13,7 +12,6 @@ class BitcoinModule final : public clang::tidy::ClangTidyModule
1312
public:
1413
void addCheckFactories(clang::tidy::ClangTidyCheckFactories& CheckFactories) override
1514
{
16-
CheckFactories.registerCheck<bitcoin::LogPrintfCheck>("bitcoin-unterminated-logprintf");
1715
CheckFactories.registerCheck<bitcoin::NonTrivialThreadLocal>("bitcoin-nontrivial-threadlocal");
1816
}
1917
};

contrib/devtools/bitcoin-tidy/example_logprintf.cpp

-108
This file was deleted.

contrib/devtools/bitcoin-tidy/logprintf.cpp

-60
This file was deleted.

contrib/devtools/bitcoin-tidy/logprintf.h

-29
This file was deleted.

src/logging.cpp

+4-17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <logging.h>
77
#include <memusage.h>
8+
#include <util/check.h>
89
#include <util/fs.h>
910
#include <util/string.h>
1011
#include <util/threadnames.h>
@@ -368,6 +369,8 @@ static size_t MemUsage(const BCLog::Logger::BufferedLog& buflog)
368369

369370
void BCLog::Logger::FormatLogStrInPlace(std::string& str, BCLog::LogFlags category, BCLog::Level level, std::string_view source_file, int source_line, std::string_view logging_function, std::string_view threadname, SystemClock::time_point now, std::chrono::seconds mocktime) const
370371
{
372+
if (!str.ends_with('\n')) str.push_back('\n');
373+
371374
str.insert(0, GetLogPrefix(category, level));
372375

373376
if (m_log_sourcelocations) {
@@ -391,21 +394,7 @@ void BCLog::Logger::LogPrintStr_(std::string_view str, std::string_view logging_
391394
{
392395
std::string str_prefixed = LogEscapeMessage(str);
393396

394-
const bool starts_new_line = m_started_new_line;
395-
m_started_new_line = !str.empty() && str[str.size()-1] == '\n';
396-
397397
if (m_buffering) {
398-
if (!starts_new_line) {
399-
if (!m_msgs_before_open.empty()) {
400-
m_msgs_before_open.back().str += str_prefixed;
401-
m_cur_buffer_memusage += str_prefixed.size();
402-
return;
403-
} else {
404-
// unlikely edge case; add a marker that something was trimmed
405-
str_prefixed.insert(0, "[...] ");
406-
}
407-
}
408-
409398
{
410399
BufferedLog buf{
411400
.now=SystemClock::now(),
@@ -435,9 +424,7 @@ void BCLog::Logger::LogPrintStr_(std::string_view str, std::string_view logging_
435424
return;
436425
}
437426

438-
if (starts_new_line) {
439-
FormatLogStrInPlace(str_prefixed, category, level, source_file, source_line, logging_function, util::ThreadGetInternalName(), SystemClock::now(), GetMockTime());
440-
}
427+
FormatLogStrInPlace(str_prefixed, category, level, source_file, source_line, logging_function, util::ThreadGetInternalName(), SystemClock::now(), GetMockTime());
441428

442429
if (m_print_to_console) {
443430
// print to console

src/logging.h

-8
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,6 @@ namespace BCLog {
105105
size_t m_cur_buffer_memusage GUARDED_BY(m_cs){0};
106106
size_t m_buffer_lines_discarded GUARDED_BY(m_cs){0};
107107

108-
/**
109-
* m_started_new_line is a state variable that will suppress printing of
110-
* the timestamp when multiple calls are made that don't end in a
111-
* newline.
112-
*/
113-
std::atomic_bool m_started_new_line{true};
114-
115108
//! Category-specific log level. Overrides `m_log_level`.
116109
std::unordered_map<LogFlags, Level> m_category_log_levels GUARDED_BY(m_cs);
117110

@@ -253,7 +246,6 @@ inline void LogPrintFormatInternal(std::string_view logging_function, std::strin
253246
try {
254247
log_msg = tfm::format(fmt, args...);
255248
} catch (tinyformat::format_error& fmterr) {
256-
/* Original format string will have newline so don't add one here */
257249
log_msg = "Error \"" + std::string{fmterr.what()} + "\" while formatting log message: " + fmt.fmt;
258250
}
259251
LogInstance().LogPrintStr(log_msg, logging_function, source_file, source_line, flag, level);

src/test/logging_tests.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,12 @@ BOOST_AUTO_TEST_CASE(logging_timer)
8686
BOOST_FIXTURE_TEST_CASE(logging_LogPrintStr, LogSetup)
8787
{
8888
LogInstance().m_log_sourcelocations = true;
89-
LogInstance().LogPrintStr("foo1: bar1\n", "fn1", "src1", 1, BCLog::LogFlags::NET, BCLog::Level::Debug);
90-
LogInstance().LogPrintStr("foo2: bar2\n", "fn2", "src2", 2, BCLog::LogFlags::NET, BCLog::Level::Info);
91-
LogInstance().LogPrintStr("foo3: bar3\n", "fn3", "src3", 3, BCLog::LogFlags::ALL, BCLog::Level::Debug);
92-
LogInstance().LogPrintStr("foo4: bar4\n", "fn4", "src4", 4, BCLog::LogFlags::ALL, BCLog::Level::Info);
93-
LogInstance().LogPrintStr("foo5: bar5\n", "fn5", "src5", 5, BCLog::LogFlags::NONE, BCLog::Level::Debug);
94-
LogInstance().LogPrintStr("foo6: bar6\n", "fn6", "src6", 6, BCLog::LogFlags::NONE, BCLog::Level::Info);
89+
LogInstance().LogPrintStr("foo1: bar1", "fn1", "src1", 1, BCLog::LogFlags::NET, BCLog::Level::Debug);
90+
LogInstance().LogPrintStr("foo2: bar2", "fn2", "src2", 2, BCLog::LogFlags::NET, BCLog::Level::Info);
91+
LogInstance().LogPrintStr("foo3: bar3", "fn3", "src3", 3, BCLog::LogFlags::ALL, BCLog::Level::Debug);
92+
LogInstance().LogPrintStr("foo4: bar4", "fn4", "src4", 4, BCLog::LogFlags::ALL, BCLog::Level::Info);
93+
LogInstance().LogPrintStr("foo5: bar5", "fn5", "src5", 5, BCLog::LogFlags::NONE, BCLog::Level::Debug);
94+
LogInstance().LogPrintStr("foo6: bar6", "fn6", "src6", 6, BCLog::LogFlags::NONE, BCLog::Level::Info);
9595
std::ifstream file{tmp_log_path};
9696
std::vector<std::string> log_lines;
9797
for (std::string log; std::getline(file, log);) {
@@ -133,11 +133,11 @@ BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacrosDeprecated, LogSetup)
133133

134134
BOOST_FIXTURE_TEST_CASE(logging_LogPrintMacros, LogSetup)
135135
{
136-
LogTrace(BCLog::NET, "foo6: %s\n", "bar6"); // not logged
137-
LogDebug(BCLog::NET, "foo7: %s\n", "bar7");
138-
LogInfo("foo8: %s\n", "bar8");
139-
LogWarning("foo9: %s\n", "bar9");
140-
LogError("foo10: %s\n", "bar10");
136+
LogTrace(BCLog::NET, "foo6: %s", "bar6"); // not logged
137+
LogDebug(BCLog::NET, "foo7: %s", "bar7");
138+
LogInfo("foo8: %s", "bar8");
139+
LogWarning("foo9: %s", "bar9");
140+
LogError("foo10: %s", "bar10");
141141
std::ifstream file{tmp_log_path};
142142
std::vector<std::string> log_lines;
143143
for (std::string log; std::getline(file, log);) {

test/lint/lint-format-strings.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ def main():
6262

6363
matching_files_filtered = []
6464
for matching_file in matching_files:
65-
if not re.search('^src/(leveldb|secp256k1|minisketch|tinyformat|test/fuzz/strprintf.cpp)|contrib/devtools/bitcoin-tidy/example_logprintf.cpp', matching_file):
65+
if not re.search('^src/(leveldb|secp256k1|minisketch|tinyformat|test/fuzz/strprintf.cpp)', matching_file):
6666
matching_files_filtered.append(matching_file)
6767
matching_files_filtered.sort()
6868

0 commit comments

Comments
 (0)