diff --git a/CMakeLists.txt b/CMakeLists.txt index a4a1474b9..e76fb1486 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -815,6 +815,37 @@ if (BUILD_TESTING) set_tests_properties (cleanup_immediately PROPERTIES FIXTURES_REQUIRED logcleanuptest) set_tests_properties (cleanup_with_absolute_prefix PROPERTIES FIXTURES_REQUIRED logcleanuptest) set_tests_properties (cleanup_with_relative_prefix PROPERTIES FIXTURES_REQUIRED logcleanuptest) + + add_executable (striplog0_unittest + src/striplog_unittest.cc + ) + target_compile_definitions (striplog0_unittest PRIVATE GOOGLE_STRIP_LOG=0) + target_link_libraries (striplog0_unittest PRIVATE glog_test) + + add_test (NAME striplog0 COMMAND striplog0_unittest) + + add_executable (striplog2_unittest + src/striplog_unittest.cc + ) + target_compile_definitions (striplog2_unittest PRIVATE GOOGLE_STRIP_LOG=2) + target_link_libraries (striplog2_unittest PRIVATE glog_test) + + add_test (NAME striplog2 COMMAND striplog2_unittest) + + add_executable (striplog10_unittest + src/striplog_unittest.cc + ) + target_compile_definitions (striplog10_unittest PRIVATE GOOGLE_STRIP_LOG=10) + target_link_libraries (striplog10_unittest PRIVATE glog_test) + + add_test (NAME striplog10 COMMAND striplog10_unittest) + + set_tests_properties ( + striplog0 + striplog2 + striplog10 + PROPERTIES WILL_FAIL ON + ) endif (BUILD_TESTING) install (TARGETS glog diff --git a/src/glog/logging.h.in b/src/glog/logging.h.in index f878231c8..f213c8837 100644 --- a/src/glog/logging.h.in +++ b/src/glog/logging.h.in @@ -50,6 +50,7 @@ # include #endif #include +#include #if defined(_MSC_VER) #define GLOG_MSVC_PUSH_DISABLE_WARNING(n) __pragma(warning(push)) \ @@ -62,6 +63,16 @@ #include "glog/platform.h" +#if defined(__has_attribute) +#if __has_attribute(used) +#define GLOG_USED __attribute__((used)) +#endif // __has_attribute(used) +#endif // defined(__has_attribute) + +#if !defined(GLOG_USED) +#define GLOG_USED +#endif // !defined(GLOG_USED) + #if @ac_cv_have_glog_export@ #include "glog/export.h" #endif @@ -1357,22 +1368,30 @@ GLOG_MSVC_PUSH_DISABLE_WARNING(4275) class GLOG_EXPORT LogStream : public std::ostream { GLOG_MSVC_POP_WARNING() public: -#if defined __has_attribute -# if __has_attribute (used) - // In some cases, like when compiling glog as a static library with GCC and - // linking against a Clang-built executable, this constructor will be - // removed by the linker. We use this attribute to prevent the linker from - // discarding it. - __attribute__ ((used)) -# endif -#endif - LogStream(char *buf, int len, int64 ctr) - : std::ostream(nullptr), - streambuf_(buf, len), - ctr_(ctr), - self_(this) { - rdbuf(&streambuf_); - } + // In some cases, like when compiling glog as a static library with GCC and + // linking against a Clang-built executable, this constructor will be + // removed by the linker. We use this attribute to prevent the linker from + // discarding it. + GLOG_USED + LogStream(char* buf, int len, int64 ctr) + : std::ostream(nullptr), streambuf_(buf, len), ctr_(ctr), self_(this) { + rdbuf(&streambuf_); + } + + LogStream(LogStream&& other) noexcept + : std::ostream(nullptr), + streambuf_(std::move(other.streambuf_)), + ctr_(std::exchange(other.ctr_, 0)), + self_(this) { + rdbuf(&streambuf_); + } + + LogStream& operator=(LogStream&& other) noexcept { + streambuf_ = std::move(other.streambuf_); + ctr_ = std::exchange(other.ctr_, 0); + rdbuf(&streambuf_); + return *this; + } int64 ctr() const { return ctr_; } void set_ctr(int64 ctr) { ctr_ = ctr; } @@ -1383,9 +1402,10 @@ GLOG_MSVC_POP_WARNING() char* pbase() const { return streambuf_.pbase(); } char* str() const { return pbase(); } + LogStream(const LogStream&) = delete; + LogStream& operator=(const LogStream&) = delete; + private: - LogStream(const LogStream&); - LogStream& operator=(const LogStream&); base_logging::LogStreamBuf streambuf_; int64 ctr_; // Counter hack (for the LOG_EVERY_X() macro) LogStream *self_; // Consistency check hack @@ -1799,7 +1819,7 @@ class GLOG_EXPORT NullStream : public LogMessage::LogStream { // A very short buffer for messages (which we discard anyway). This // will be needed if NullStream& converted to LogStream& (e.g. as a // result of a conditional expression). - char message_buffer_[2]; + char message_buffer_[3]; }; // Do nothing. This operator is inline, allowing the message to be @@ -1816,7 +1836,9 @@ inline NullStream& operator<<(NullStream &str, const T &) { return str; } class GLOG_EXPORT NullStreamFatal : public NullStream { public: using NullStream::NullStream; - [[noreturn]] ~NullStreamFatal(); + [[noreturn]] + // Prevent the linker from discarding the destructor. + GLOG_USED ~NullStreamFatal(); }; // Install a signal handler that will dump signal information and a stack diff --git a/src/logging.cc b/src/logging.cc index bfafe7cdd..c05e385ad 100644 --- a/src/logging.cc +++ b/src/logging.cc @@ -1,4 +1,4 @@ -// Copyright (c) 1999, Google Inc. +// Copyright (c) 2023, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -1932,13 +1932,17 @@ void LogMessage::RecordCrashReason( GLOG_EXPORT logging_fail_func_t g_logging_fail_func = reinterpret_cast(&abort); -NullStream::NullStream() : LogMessage::LogStream(message_buffer_, 1, 0) {} +NullStream::NullStream() : LogMessage::LogStream(message_buffer_, 2, 0) {} NullStream::NullStream(const char* /*file*/, int /*line*/, const CheckOpString& /*result*/) - : LogMessage::LogStream(message_buffer_, 1, 0) {} + : LogMessage::LogStream(message_buffer_, 2, 0) {} NullStream& NullStream::stream() { return *this; } -NullStreamFatal::~NullStreamFatal() { _exit(EXIT_FAILURE); } +NullStreamFatal::~NullStreamFatal() { + // Cannot use g_logging_fail_func here as it may output the backtrace which + // would be inconsistent with NullStream behavior. + std::abort(); +} void InstallFailureFunction(logging_fail_func_t fail_func) { g_logging_fail_func = fail_func; diff --git a/src/logging_striplog_test.sh b/src/logging_striplog_test.sh index 73492bda7..bb6d0e2b1 100755 --- a/src/logging_striplog_test.sh +++ b/src/logging_striplog_test.sh @@ -1,6 +1,6 @@ #! /bin/sh # -# Copyright (c) 2007, Google Inc. +# Copyright (c) 2023, Google Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without @@ -32,15 +32,15 @@ # Author: Sergey Ioffe get_strings () { - if test -e ".libs/$1"; then - binary=".libs/$1" + if test -e "$1"; then + binary="$1" elif test -e "$1.exe"; then binary="$1.exe" else echo "We coundn't find $1 binary." exit 1 fi - + strings -n 10 $binary | sort | awk '/TESTMESSAGE/ {printf "%s ", $2}' } @@ -60,20 +60,21 @@ die () { # Check that the string literals are appropriately stripped. This will # not be the case in debug mode. -mode=`GLOG_check_mode=1 ./logging_striptest0 2> /dev/null` +mode=`GLOG_check_mode=1 ./striplog0_unittest 2> /dev/null` +echo $mode if [ "$mode" = "opt" ]; then echo "In OPT mode" - check_eq "`get_strings logging_striptest0`" "COND ERROR FATAL INFO USAGE WARNING " - check_eq "`get_strings logging_striptest2`" "COND ERROR FATAL USAGE " - check_eq "`get_strings logging_striptest10`" "" + check_eq "`get_strings striplog0_unittest`" "COND ERROR FATAL INFO WARNING " + check_eq "`get_strings striplog2_unittest`" "COND ERROR FATAL " + check_eq "`get_strings striplog10_unittest`" "" else echo "In DBG mode; not checking strings" fi # Check that LOG(FATAL) aborts even for large STRIP_LOG -./logging_striptest2 2>/dev/null && die "Did not abort for STRIP_LOG=2" -./logging_striptest10 2>/dev/null && die "Did not abort for STRIP_LOG=10" +./striplog2_unittest 2>/dev/null && die "Did not abort for STRIP_LOG=2" +./striplog10_unittest 2>/dev/null && die "Did not abort for STRIP_LOG=10" echo "PASS" diff --git a/src/logging_striptest10.cc b/src/logging_striptest10.cc deleted file mode 100644 index f6e1078f3..000000000 --- a/src/logging_striptest10.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: Sergey Ioffe - -#define GOOGLE_STRIP_LOG 10 - -// Include the actual test. -#include "logging_striptest_main.cc" diff --git a/src/logging_striptest2.cc b/src/logging_striptest2.cc deleted file mode 100644 index a64685c9e..000000000 --- a/src/logging_striptest2.cc +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: Sergey Ioffe - -#define GOOGLE_STRIP_LOG 2 - -// Include the actual test. -#include "logging_striptest_main.cc" diff --git a/src/logging_striptest_main.cc b/src/striplog_unittest.cc similarity index 77% rename from src/logging_striptest_main.cc rename to src/striplog_unittest.cc index 7158ab285..d87a50074 100644 --- a/src/logging_striptest_main.cc +++ b/src/striplog_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2007, Google Inc. +// Copyright (c) 2023, Google Inc. // All rights reserved. // // Redistribution and use in source and binary forms, with or without @@ -31,7 +31,9 @@ // The common part of the striplog tests. +#include #include +#include #include #include @@ -39,7 +41,6 @@ #include "config.h" #include "glog/logging.h" -DECLARE_bool(logtostderr); GLOG_DEFINE_bool(check_mode, false, "Prints 'opt' or 'dbg'"); using std::string; @@ -49,15 +50,27 @@ int CheckNoReturn(bool b) { string s; if (b) { LOG(FATAL) << "Fatal"; + return 0; // Workaround for MSVC warning C4715 } else { return 0; } } -struct A { }; -std::ostream &operator<<(std::ostream &str, const A&) {return str;} +struct A {}; +std::ostream &operator<<(std::ostream &str, const A &) { return str; } + +namespace { +void handle_abort(int /*code*/) { std::exit(EXIT_FAILURE); } +} // namespace + +int main(int, char *argv[]) { +#if defined(_MSC_VER) + // Avoid presenting an interactive dialog that will cause the test to time + // out. + _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); +#endif // defined(_MSC_VER) + std::signal(SIGABRT, handle_abort); -int main(int, char* argv[]) { FLAGS_logtostderr = true; InitGoogleLogging(argv[0]); if (FLAGS_check_mode) { @@ -65,8 +78,8 @@ int main(int, char* argv[]) { return 0; } LOG(INFO) << "TESTMESSAGE INFO"; - LOG(WARNING) << 2 << "something" << "TESTMESSAGE WARNING" - << 1 << 'c' << A() << std::endl; + LOG(WARNING) << 2 << "something" + << "TESTMESSAGE WARNING" << 1 << 'c' << A() << std::endl; LOG(ERROR) << "TESTMESSAGE ERROR"; bool flag = true; (flag ? LOG(INFO) : LOG(ERROR)) << "TESTMESSAGE COND";