fix: better encapsulate internals (#1055)

This commit is contained in:
Sergiu Deitsch 2024-01-09 23:51:43 +01:00 committed by GitHub
parent 2b5a53c880
commit ec455f2cc1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 392 additions and 265 deletions

View File

@ -142,6 +142,7 @@ check_type_size (ssize_t HAVE_SSIZE_T LANGUAGE CXX)
check_cxx_symbol_exists (dladdr dlfcn.h HAVE_DLADDR) check_cxx_symbol_exists (dladdr dlfcn.h HAVE_DLADDR)
check_cxx_symbol_exists (fcntl fcntl.h HAVE_FCNTL) check_cxx_symbol_exists (fcntl fcntl.h HAVE_FCNTL)
check_cxx_symbol_exists (posix_fadvise fcntl.h HAVE_POSIX_FADVISE)
check_cxx_symbol_exists (pread unistd.h HAVE_PREAD) check_cxx_symbol_exists (pread unistd.h HAVE_PREAD)
check_cxx_symbol_exists (pwrite unistd.h HAVE_PWRITE) check_cxx_symbol_exists (pwrite unistd.h HAVE_PWRITE)
check_cxx_symbol_exists (sigaction csignal HAVE_SIGACTION) check_cxx_symbol_exists (sigaction csignal HAVE_SIGACTION)
@ -364,6 +365,8 @@ set (GLOG_SRCS
src/logging.cc src/logging.cc
src/raw_logging.cc src/raw_logging.cc
src/signalhandler.cc src/signalhandler.cc
src/stacktrace.cc
src/stacktrace.h
src/symbolize.cc src/symbolize.cc
src/symbolize.h src/symbolize.h
src/utilities.cc src/utilities.cc

View File

@ -48,8 +48,6 @@ def glog_library(with_gflags = 1, **kwargs):
common_copts = [ common_copts = [
"-std=c++14", "-std=c++14",
"-DGLOG_BAZEL_BUILD",
"-DHAVE_STRING_H",
"-I%s/glog_internal" % gendir, "-I%s/glog_internal" % gendir,
] + (["-DGLOG_USE_GFLAGS"] if with_gflags else []) ] + (["-DGLOG_USE_GFLAGS"] if with_gflags else [])
@ -74,6 +72,7 @@ def glog_library(with_gflags = 1, **kwargs):
"-DGLOG_EXPORT=__attribute__((visibility(\\\"default\\\")))", "-DGLOG_EXPORT=__attribute__((visibility(\\\"default\\\")))",
"-DGLOG_NO_EXPORT=__attribute__((visibility(\\\"default\\\")))", "-DGLOG_NO_EXPORT=__attribute__((visibility(\\\"default\\\")))",
"-DHAVE_MODE_T", "-DHAVE_MODE_T",
"-DHAVE_POSIX_FADVISE",
"-DHAVE_SSIZE_T", "-DHAVE_SSIZE_T",
"-DHAVE_SYS_TYPES_H", "-DHAVE_SYS_TYPES_H",
# For src/utilities.cc. # For src/utilities.cc.
@ -102,10 +101,11 @@ def glog_library(with_gflags = 1, **kwargs):
windows_only_copts = [ windows_only_copts = [
# Override -DGLOG_EXPORT= from the cc_library's defines. # Override -DGLOG_EXPORT= from the cc_library's defines.
"-DGLOG_EXPORT=__declspec(dllexport)", "-DGLOG_EXPORT=__declspec(dllexport)",
"-DGLOG_NO_EXPORT=",
"-DGLOG_NO_ABBREVIATED_SEVERITIES", "-DGLOG_NO_ABBREVIATED_SEVERITIES",
"-DGLOG_NO_EXPORT=",
"-DGLOG_USE_WINDOWS_PORT", "-DGLOG_USE_WINDOWS_PORT",
"-DHAVE__CHSIZE_S", "-DHAVE__CHSIZE_S",
"-DHAVE_DBGHELP",
"-I" + src_windows, "-I" + src_windows,
] ]
@ -115,7 +115,6 @@ def glog_library(with_gflags = 1, **kwargs):
] ]
windows_only_srcs = [ windows_only_srcs = [
"src/glog/log_severity.h",
"src/windows/dirent.h", "src/windows/dirent.h",
"src/windows/port.cc", "src/windows/port.cc",
"src/windows/port.h", "src/windows/port.h",
@ -127,13 +126,15 @@ def glog_library(with_gflags = 1, **kwargs):
# GLOG_EXPORT is normally set by export.h, but that's not # GLOG_EXPORT is normally set by export.h, but that's not
# generated for Bazel. # generated for Bazel.
"@bazel_tools//src/conditions:windows": [ "@bazel_tools//src/conditions:windows": [
"GLOG_EXPORT=",
"GLOG_DEPRECATED=__declspec(deprecated)", "GLOG_DEPRECATED=__declspec(deprecated)",
"GLOG_EXPORT=",
"GLOG_NO_ABBREVIATED_SEVERITIES", "GLOG_NO_ABBREVIATED_SEVERITIES",
"GLOG_NO_EXPORT=",
], ],
"//conditions:default": [ "//conditions:default": [
"GLOG_DEPRECATED=__attribute__((deprecated))", "GLOG_DEPRECATED=__attribute__((deprecated))",
"GLOG_EXPORT=__attribute__((visibility(\\\"default\\\")))", "GLOG_EXPORT=__attribute__((visibility(\\\"default\\\")))",
"GLOG_NO_EXPORT=__attribute__((visibility(\\\"default\\\")))",
], ],
}) })
@ -171,6 +172,8 @@ def glog_library(with_gflags = 1, **kwargs):
"src/logging.cc", "src/logging.cc",
"src/raw_logging.cc", "src/raw_logging.cc",
"src/signalhandler.cc", "src/signalhandler.cc",
"src/stacktrace.cc",
"src/stacktrace.h",
"src/stacktrace_generic-inl.h", "src/stacktrace_generic-inl.h",
"src/stacktrace_libunwind-inl.h", "src/stacktrace_libunwind-inl.h",
"src/stacktrace_powerpc-inl.h", "src/stacktrace_powerpc-inl.h",
@ -180,6 +183,7 @@ def glog_library(with_gflags = 1, **kwargs):
"src/symbolize.cc", "src/symbolize.cc",
"src/symbolize.h", "src/symbolize.h",
"src/utilities.cc", "src/utilities.cc",
"src/utilities.h",
"src/vlog_is_on.cc", "src/vlog_is_on.cc",
] + select({ ] + select({
"@bazel_tools//src/conditions:windows": windows_only_srcs, "@bazel_tools//src/conditions:windows": windows_only_srcs,

View File

@ -31,6 +31,9 @@
/* Define if you have the 'pread' function */ /* Define if you have the 'pread' function */
#cmakedefine HAVE_PREAD #cmakedefine HAVE_PREAD
/* Define if you have the 'posix_fadvise' function in <fcntl.h> */
#cmakedefine HAVE_POSIX_FADVISE
/* Define to 1 if you have the <pwd.h> header file. */ /* Define to 1 if you have the <pwd.h> header file. */
#cmakedefine HAVE_PWD_H #cmakedefine HAVE_PWD_H

View File

@ -37,7 +37,6 @@
#include "demangle.h" #include "demangle.h"
#include <algorithm> #include <algorithm>
#include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <limits> #include <limits>
@ -52,6 +51,7 @@
#endif #endif
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
#if !defined(GLOG_OS_WINDOWS) && !defined(HAVE___CXA_DEMANGLE) #if !defined(GLOG_OS_WINDOWS) && !defined(HAVE___CXA_DEMANGLE)
namespace { namespace {
@ -1359,4 +1359,5 @@ bool Demangle(const char* mangled, char* out, size_t out_size) {
#endif #endif
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -67,19 +67,28 @@
// C++ ABI in the future. // C++ ABI in the future.
// //
#ifndef BASE_DEMANGLE_H_ #ifndef GLOG_INTERNAL_DEMANGLE_H
#define BASE_DEMANGLE_H_ #define GLOG_INTERNAL_DEMANGLE_H
#include "config.h" #include <cstddef>
#include "glog/logging.h"
#if defined(GLOG_USE_GLOG_EXPORT)
# include "glog/export.h"
#endif
#if !defined(GLOG_NO_EXPORT)
# error "demangle.h" was not included correctly.
#endif
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// Demangle "mangled". On success, return true and write the // Demangle "mangled". On success, return true and write the
// demangled symbol name to "out". Otherwise, return false. // demangled symbol name to "out". Otherwise, return false.
// "out" is modified even if demangling is unsuccessful. // "out" is modified even if demangling is unsuccessful.
bool GLOG_EXPORT Demangle(const char* mangled, char* out, size_t out_size); bool GLOG_NO_EXPORT Demangle(const char* mangled, char* out, size_t out_size);
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
#endif // BASE_DEMANGLE_H_ #endif // GLOG_INTERNAL_DEMANGLE_H

View File

@ -95,8 +95,6 @@ constexpr int NUM_SEVERITIES = 4;
# define DFATAL_LEVEL FATAL # define DFATAL_LEVEL FATAL
#endif #endif
extern GLOG_EXPORT const char* const LogSeverityNames[NUM_SEVERITIES];
// NDEBUG usage helpers related to (RAW_)DCHECK: // NDEBUG usage helpers related to (RAW_)DCHECK:
// //
// DEBUG_MODE is for small !NDEBUG uses like // DEBUG_MODE is for small !NDEBUG uses like

View File

@ -56,7 +56,7 @@
# include "glog/export.h" # include "glog/export.h"
#endif #endif
#if !defined(GLOG_EXPORT) #if !defined(GLOG_EXPORT) || !defined(GLOG_NO_EXPORT)
# error <glog/logging.h> was not included correctly. See the documention for how to consume the library. # error <glog/logging.h> was not included correctly. See the documention for how to consume the library.
#endif #endif
@ -580,13 +580,16 @@ class LogSink; // defined below
LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \ LOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN(!(condition))) \
<< "Check failed: " #condition " " << "Check failed: " #condition " "
namespace logging {
namespace internal {
// A container for a string pointer which can be evaluated to a bool - // A container for a string pointer which can be evaluated to a bool -
// true iff the pointer is nullptr. // true iff the pointer is nullptr.
struct CheckOpString { struct CheckOpString {
CheckOpString(std::string* str) : str_(str) {} CheckOpString(std::string* str) : str_(str) {}
// No destructor: if str_ is non-nullptr, we're about to LOG(FATAL), // No destructor: if str_ is non-nullptr, we're about to LOG(FATAL),
// so there's no point in cleaning up str_. // so there's no point in cleaning up str_.
operator bool() const { explicit operator bool() const noexcept {
return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != nullptr); return GOOGLE_PREDICT_BRANCH_NOT_TAKEN(str_ != nullptr);
} }
std::string* str_; std::string* str_;
@ -616,18 +619,14 @@ inline unsigned long long GetReferenceableValue(unsigned long long t) {
// This is a dummy class to define the following operator. // This is a dummy class to define the following operator.
struct DummyClassToDefineOperator {}; struct DummyClassToDefineOperator {};
} // namespace google
// Define global operator<< to declare using ::operator<<. // Define global operator<< to declare using ::operator<<.
// This declaration will allow use to use CHECK macros for user // This declaration will allow use to use CHECK macros for user
// defined classes which have operator<< (e.g., stl_logging.h). // defined classes which have operator<< (e.g., stl_logging.h).
inline std::ostream& operator<<(std::ostream& out, inline std::ostream& operator<<(std::ostream& out,
const google::DummyClassToDefineOperator&) { const DummyClassToDefineOperator&) {
return out; return out;
} }
namespace google {
// This formats a value for a failing CHECK_XX statement. Ordinarily, // This formats a value for a failing CHECK_XX statement. Ordinarily,
// it uses the definition for operator<<, with a few special cases below. // it uses the definition for operator<<, with a few special cases below.
template <typename T> template <typename T>
@ -660,8 +659,6 @@ std::string* MakeCheckOpString(const T1& v1, const T2& v2, const char* exprtext)
#endif #endif
; ;
namespace base {
// A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX // A helper class for formatting "expr (V1 vs. V2)" in a CHECK_XX
// statement. See MakeCheckOpString for sample usage. Other // statement. See MakeCheckOpString for sample usage. Other
// approaches were considered: use of a template method (e.g., // approaches were considered: use of a template method (e.g.,
@ -685,12 +682,10 @@ class GLOG_EXPORT CheckOpMessageBuilder {
std::ostringstream* stream_; std::ostringstream* stream_;
}; };
} // namespace base
template <typename T1, typename T2> template <typename T1, typename T2>
std::string* MakeCheckOpString(const T1& v1, const T2& v2, std::string* MakeCheckOpString(const T1& v1, const T2& v2,
const char* exprtext) { const char* exprtext) {
base::CheckOpMessageBuilder comb(exprtext); CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1); MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2); MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString(); return comb.NewString();
@ -717,13 +712,13 @@ std::string* MakeCheckOpString(const T1& v1, const T2& v2,
// base/logging.h provides its own #defines for the simpler names EQ, NE, etc. // base/logging.h provides its own #defines for the simpler names EQ, NE, etc.
// This happens if, for example, those are used as token names in a // This happens if, for example, those are used as token names in a
// yacc grammar. // yacc grammar.
DEFINE_CHECK_OP_IMPL(Check_EQ, DEFINE_CHECK_OP_IMPL(Check_EQ, ==)
==) // Compilation error with CHECK_EQ(nullptr, x)? DEFINE_CHECK_OP_IMPL(Check_NE, !=)
DEFINE_CHECK_OP_IMPL(Check_NE, !=) // Use CHECK(x == nullptr) instead.
DEFINE_CHECK_OP_IMPL(Check_LE, <=) DEFINE_CHECK_OP_IMPL(Check_LE, <=)
DEFINE_CHECK_OP_IMPL(Check_LT, <) DEFINE_CHECK_OP_IMPL(Check_LT, <)
DEFINE_CHECK_OP_IMPL(Check_GE, >=) DEFINE_CHECK_OP_IMPL(Check_GE, >=)
DEFINE_CHECK_OP_IMPL(Check_GT, >) DEFINE_CHECK_OP_IMPL(Check_GT, >)
#undef DEFINE_CHECK_OP_IMPL #undef DEFINE_CHECK_OP_IMPL
// Helper macro for binary operators. // Helper macro for binary operators.
@ -744,17 +739,22 @@ DEFINE_CHECK_OP_IMPL(Check_GT, >)
// in the macro. // in the macro.
typedef std::string _Check_string; typedef std::string _Check_string;
# define CHECK_OP_LOG(name, op, val1, val2, log) \ # define CHECK_OP_LOG(name, op, val1, val2, log) \
while (google::_Check_string* _result = google::Check##name##Impl( \ while (google::logging::internal::_Check_string* _result = \
google::GetReferenceableValue(val1), \ google::logging::internal::Check##name##Impl( \
google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \ google::logging::internal::GetReferenceableValue(val1), \
log(__FILE__, __LINE__, google::CheckOpString(_result)).stream() google::logging::internal::GetReferenceableValue(val2), \
#val1 " " #op " " #val2)) \
log(__FILE__, __LINE__, google::logging::internal::CheckOpString(_result)) \
.stream()
#else #else
// In optimized mode, use CheckOpString to hint to compiler that // In optimized mode, use CheckOpString to hint to compiler that
// the while condition is unlikely. // the while condition is unlikely.
# define CHECK_OP_LOG(name, op, val1, val2, log) \ # define CHECK_OP_LOG(name, op, val1, val2, log) \
while (google::CheckOpString _result = google::Check##name##Impl( \ while (google::logging::internal::CheckOpString _result = \
google::GetReferenceableValue(val1), \ google::logging::internal::Check##name##Impl( \
google::GetReferenceableValue(val2), #val1 " " #op " " #val2)) \ google::logging::internal::GetReferenceableValue(val1), \
google::logging::internal::GetReferenceableValue(val2), \
#val1 " " #op " " #val2)) \
log(__FILE__, __LINE__, _result).stream() log(__FILE__, __LINE__, _result).stream()
#endif // STATIC_ANALYSIS, DCHECK_IS_ON() #endif // STATIC_ANALYSIS, DCHECK_IS_ON()
@ -795,24 +795,30 @@ typedef std::string _Check_string;
// initializer lists. // initializer lists.
#define CHECK_NOTNULL(val) \ #define CHECK_NOTNULL(val) \
google::CheckNotNull(__FILE__, __LINE__, "'" #val "' Must be non nullptr", \ google::logging::internal::CheckNotNull( \
(val)) __FILE__, __LINE__, "'" #val "' Must be non nullptr", (val))
// Helper functions for string comparisons. // Helper functions for string comparisons.
// To avoid bloat, the definitions are in logging.cc. // To avoid bloat, the definitions are in logging.cc.
#define DECLARE_CHECK_STROP_IMPL(func, expected) \ #define DECLARE_CHECK_STROP_IMPL(func, expected) \
GLOG_EXPORT std::string* Check##func##expected##Impl( \ GLOG_EXPORT std::string* Check##func##expected##Impl( \
const char* s1, const char* s2, const char* names); const char* s1, const char* s2, const char* names);
DECLARE_CHECK_STROP_IMPL(strcmp, true) DECLARE_CHECK_STROP_IMPL(strcmp, true)
DECLARE_CHECK_STROP_IMPL(strcmp, false) DECLARE_CHECK_STROP_IMPL(strcmp, false)
DECLARE_CHECK_STROP_IMPL(strcasecmp, true) DECLARE_CHECK_STROP_IMPL(strcasecmp, true)
DECLARE_CHECK_STROP_IMPL(strcasecmp, false) DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
} // namespace internal
} // namespace logging
#undef DECLARE_CHECK_STROP_IMPL #undef DECLARE_CHECK_STROP_IMPL
// Helper macro for string comparisons. // Helper macro for string comparisons.
// Don't use this macro directly in your code, use CHECK_STREQ et al below. // Don't use this macro directly in your code, use CHECK_STREQ et al below.
#define CHECK_STROP(func, op, expected, s1, s2) \ #define CHECK_STROP(func, op, expected, s1, s2) \
while (google::CheckOpString _result = google::Check##func##expected##Impl( \ while (google::logging::internal::CheckOpString _result = \
google::logging::internal::Check##func##expected##Impl( \
(s1), (s2), #s1 " " #op " " #s2)) \ (s1), (s2), #s1 " " #op " " #s2)) \
LOG(FATAL) << *_result.str_ LOG(FATAL) << *_result.str_
@ -1181,6 +1187,12 @@ class GLOG_EXPORT LogStreamBuf : public std::streambuf {
} // namespace base_logging } // namespace base_logging
namespace logging {
namespace internal {
struct GLOG_NO_EXPORT LogMessageData;
} // namespace internal
} // namespace logging
// //
// This class more or less represents a particular log message. You // This class more or less represents a particular log message. You
// create an instance of LogMessage and then stream stuff to it. // create an instance of LogMessage and then stream stuff to it.
@ -1297,7 +1309,8 @@ class GLOG_EXPORT LogMessage {
std::string* message); std::string* message);
// A special constructor used for check failures // A special constructor used for check failures
LogMessage(const char* file, int line, const CheckOpString& result); LogMessage(const char* file, int line,
const logging::internal::CheckOpString& result);
~LogMessage(); ~LogMessage();
@ -1355,8 +1368,8 @@ class GLOG_EXPORT LogMessage {
// We keep the data in a separate struct so that each instance of // We keep the data in a separate struct so that each instance of
// LogMessage uses less stack space. // LogMessage uses less stack space.
LogMessageData* allocated_; logging::internal::LogMessageData* allocated_;
LogMessageData* data_; logging::internal::LogMessageData* data_;
LogMessageTime time_; LogMessageTime time_;
friend class LogDestination; friend class LogDestination;
@ -1371,7 +1384,8 @@ class GLOG_EXPORT LogMessage {
class GLOG_EXPORT LogMessageFatal : public LogMessage { class GLOG_EXPORT LogMessageFatal : public LogMessage {
public: public:
LogMessageFatal(const char* file, int line); LogMessageFatal(const char* file, int line);
LogMessageFatal(const char* file, int line, const CheckOpString& result); LogMessageFatal(const char* file, int line,
const logging::internal::CheckOpString& result);
[[noreturn]] ~LogMessageFatal(); [[noreturn]] ~LogMessageFatal();
}; };
@ -1388,22 +1402,6 @@ inline void LogAtLevel(LogSeverity severity, std::string const& msg) {
#define LOG_AT_LEVEL(severity) \ #define LOG_AT_LEVEL(severity) \
google::LogMessage(__FILE__, __LINE__, severity).stream() google::LogMessage(__FILE__, __LINE__, severity).stream()
// Helper for CHECK_NOTNULL().
//
// In C++11, all cases can be handled by a single function. Since the value
// category of the argument is preserved (also for rvalue references),
// member initializer lists like the one below will compile correctly:
//
// Foo()
// : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {}
template <typename T>
T CheckNotNull(const char* file, int line, const char* names, T&& t) {
if (t == nullptr) {
LogMessageFatal(file, line, new std::string(names));
}
return std::forward<T>(t);
}
// Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This // Allow folks to put a counter in the LOG_EVERY_X()'ed messages. This
// only works if ostream is a LogStream. If the ostream is not a // only works if ostream is a LogStream. If the ostream is not a
// LogStream you'll get an assert saying as much at runtime. // LogStream you'll get an assert saying as much at runtime.
@ -1429,13 +1427,29 @@ class GLOG_EXPORT ErrnoLogMessage : public LogMessage {
namespace logging { namespace logging {
namespace internal { namespace internal {
class LogMessageVoidify {
public: // Helper for CHECK_NOTNULL().
LogMessageVoidify() {} //
// In C++11, all cases can be handled by a single function. Since the value
// category of the argument is preserved (also for rvalue references),
// member initializer lists like the one below will compile correctly:
//
// Foo()
// : x_(CHECK_NOTNULL(MethodReturningUniquePtr())) {}
template <typename T>
T CheckNotNull(const char* file, int line, const char* names, T&& t) {
if (t == nullptr) {
LogMessageFatal(file, line, new std::string(names));
}
return std::forward<T>(t);
}
struct LogMessageVoidify {
// This has to be an operator with a precedence lower than << but // This has to be an operator with a precedence lower than << but
// higher than ?: // higher than ?:
void operator&(std::ostream&) {} void operator&(std::ostream&) noexcept {}
}; };
} // namespace internal } // namespace internal
} // namespace logging } // namespace logging
@ -1637,7 +1651,7 @@ class GLOG_EXPORT NullStream : public LogMessage::LogStream {
// the overloaded NullStream::operator<< will not be invoked. // the overloaded NullStream::operator<< will not be invoked.
NullStream(); NullStream();
NullStream(const char* /*file*/, int /*line*/, NullStream(const char* /*file*/, int /*line*/,
const CheckOpString& /*result*/); const logging::internal::CheckOpString& /*result*/);
NullStream& stream(); NullStream& stream();
private: private:

View File

@ -52,6 +52,8 @@
# define GLOG_OS_OPENBSD # define GLOG_OS_OPENBSD
#elif defined(__EMSCRIPTEN__) #elif defined(__EMSCRIPTEN__)
# define GLOG_OS_EMSCRIPTEN # define GLOG_OS_EMSCRIPTEN
#elif defined(__ANDROID__)
# define GLOG_OS_ANDROID
#else #else
// TODO(hamaji): Add other platforms. // TODO(hamaji): Add other platforms.
#error Platform not supported by glog. Please consider to contribute platform information by submitting a pull request on Github. #error Platform not supported by glog. Please consider to contribute platform information by submitting a pull request on Github.

View File

@ -51,12 +51,16 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "utilities.h" #include "config.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#if defined(GLOG_USE_WINDOWS_PORT)
# include "port.h"
#endif // defined(GLOG_USE_WINDOWS_PORT)
#include "base/commandlineflags.h" #include "base/commandlineflags.h"
#include "utilities.h"
#if __cplusplus < 201103L && !defined(_MSC_VER) #if __cplusplus < 201103L && !defined(_MSC_VER)
# define GOOGLE_GLOG_THROW_BAD_ALLOC throw(std::bad_alloc) # define GOOGLE_GLOG_THROW_BAD_ALLOC throw(std::bad_alloc)
@ -339,20 +343,20 @@ class CapturedStream {
uncaptured_fd_; // where the stream was originally being sent to uncaptured_fd_; // where the stream was originally being sent to
string filename_; // file where stream is being saved string filename_; // file where stream is being saved
}; };
static std::unique_ptr<CapturedStream> s_captured_streams[STDERR_FILENO + 1]; static std::map<int, std::unique_ptr<CapturedStream>> s_captured_streams;
// Redirect a file descriptor to a file. // Redirect a file descriptor to a file.
// fd - Should be STDOUT_FILENO or STDERR_FILENO // fd - Should be stdout or stderr
// filename - File where output should be stored // filename - File where output should be stored
static inline void CaptureTestOutput(int fd, const string& filename) { static inline void CaptureTestOutput(int fd, const string& filename) {
CHECK((fd == STDOUT_FILENO) || (fd == STDERR_FILENO)); CHECK((fd == fileno(stdout)) || (fd == fileno(stderr)));
CHECK(s_captured_streams[fd] == nullptr); CHECK(s_captured_streams.find(fd) == s_captured_streams.end());
s_captured_streams[fd] = std::make_unique<CapturedStream>(fd, filename); s_captured_streams[fd] = std::make_unique<CapturedStream>(fd, filename);
} }
static inline void CaptureTestStdout() { static inline void CaptureTestStdout() {
CaptureTestOutput(STDOUT_FILENO, FLAGS_test_tmpdir + "/captured.out"); CaptureTestOutput(fileno(stdout), FLAGS_test_tmpdir + "/captured.out");
} }
static inline void CaptureTestStderr() { static inline void CaptureTestStderr() {
CaptureTestOutput(STDERR_FILENO, FLAGS_test_tmpdir + "/captured.err"); CaptureTestOutput(fileno(stderr), FLAGS_test_tmpdir + "/captured.err");
} }
// Return the size (in bytes) of a file // Return the size (in bytes) of a file
static inline size_t GetFileSize(FILE* file) { static inline size_t GetFileSize(FILE* file) {
@ -379,11 +383,11 @@ static inline string ReadEntireFile(FILE* file) {
return std::string(content.data(), bytes_read); return std::string(content.data(), bytes_read);
} }
// Get the captured stdout (when fd is STDOUT_FILENO) or stderr (when // Get the captured stdout or stderr as a string
// fd is STDERR_FILENO) as a string
static inline string GetCapturedTestOutput(int fd) { static inline string GetCapturedTestOutput(int fd) {
CHECK(fd == STDOUT_FILENO || fd == STDERR_FILENO); CHECK((fd == fileno(stdout)) || (fd == fileno(stderr)));
std::unique_ptr<CapturedStream> cap = std::move(s_captured_streams[fd]); std::unique_ptr<CapturedStream> cap = std::move(s_captured_streams.at(fd));
s_captured_streams.erase(fd);
CHECK(cap) << ": did you forget CaptureTestStdout() or CaptureTestStderr()?"; CHECK(cap) << ": did you forget CaptureTestStdout() or CaptureTestStderr()?";
// Make sure everything is flushed. // Make sure everything is flushed.
@ -398,7 +402,7 @@ static inline string GetCapturedTestOutput(int fd) {
} }
// Get the captured stderr of a test as a string. // Get the captured stderr of a test as a string.
static inline string GetCapturedTestStderr() { static inline string GetCapturedTestStderr() {
return GetCapturedTestOutput(STDERR_FILENO); return GetCapturedTestOutput(fileno(stderr));
} }
static const std::size_t kLoggingPrefixLength = 9; static const std::size_t kLoggingPrefixLength = 9;
@ -499,7 +503,9 @@ static inline void WriteToFile(const string& body, const string& file) {
static inline bool MungeAndDiffTest(const string& golden_filename, static inline bool MungeAndDiffTest(const string& golden_filename,
CapturedStream* cap) { CapturedStream* cap) {
if (cap == s_captured_streams[STDOUT_FILENO].get()) { auto pos = s_captured_streams.find(fileno(stdout));
if (pos != s_captured_streams.end() && cap == pos->second.get()) {
CHECK(cap) << ": did you forget CaptureTestStdout()?"; CHECK(cap) << ": did you forget CaptureTestStdout()?";
} else { } else {
CHECK(cap) << ": did you forget CaptureTestStderr()?"; CHECK(cap) << ": did you forget CaptureTestStderr()?";
@ -535,12 +541,12 @@ static inline bool MungeAndDiffTest(const string& golden_filename,
static inline bool MungeAndDiffTestStderr(const string& golden_filename) { static inline bool MungeAndDiffTestStderr(const string& golden_filename) {
return MungeAndDiffTest(golden_filename, return MungeAndDiffTest(golden_filename,
s_captured_streams[STDERR_FILENO].get()); s_captured_streams.at(fileno(stderr)).get());
} }
static inline bool MungeAndDiffTestStdout(const string& golden_filename) { static inline bool MungeAndDiffTestStdout(const string& golden_filename) {
return MungeAndDiffTest(golden_filename, return MungeAndDiffTest(golden_filename,
s_captured_streams[STDOUT_FILENO].get()); s_captured_streams.at(fileno(stdout)).get());
} }
// Save flags used from logging_unittest.cc. // Save flags used from logging_unittest.cc.

View File

@ -48,12 +48,10 @@
#include <utility> #include <utility>
#include "config.h" #include "config.h"
#include "glog/platform.h"
#include "glog/raw_logging.h" #include "glog/raw_logging.h"
#include "utilities.h"
#ifdef HAVE_STACKTRACE
#include "stacktrace.h" #include "stacktrace.h"
#endif #include "utilities.h"
#ifdef GLOG_OS_WINDOWS #ifdef GLOG_OS_WINDOWS
# include "windows/dirent.h" # include "windows/dirent.h"
@ -217,6 +215,7 @@ static bool TerminalSupportsColor() {
namespace google { namespace google {
GLOG_NO_EXPORT
std::string StrError(int err); std::string StrError(int err);
enum GLogColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW }; enum GLogColor { COLOR_DEFAULT, COLOR_RED, COLOR_GREEN, COLOR_YELLOW };
@ -283,13 +282,15 @@ static uint32 MaxLogSize() {
// is so that streaming can be done more efficiently. // is so that streaming can be done more efficiently.
const size_t LogMessage::kMaxLogMessageLen = 30000; const size_t LogMessage::kMaxLogMessageLen = 30000;
struct LogMessage::LogMessageData { namespace logging {
namespace internal {
struct LogMessageData {
LogMessageData(); LogMessageData();
int preserved_errno_; // preserved errno int preserved_errno_; // preserved errno
// Buffer space; contains complete message text. // Buffer space; contains complete message text.
char message_text_[LogMessage::kMaxLogMessageLen + 1]; char message_text_[LogMessage::kMaxLogMessageLen + 1];
LogStream stream_; LogMessage::LogStream stream_;
LogSeverity severity_; // What level is this LogMessage logged at? LogSeverity severity_; // What level is this LogMessage logged at?
int line_; // line number where logging call is. int line_; // line number where logging call is.
void (LogMessage::*send_method_)(); // Call this in destructor to send void (LogMessage::*send_method_)(); // Call this in destructor to send
@ -311,6 +312,8 @@ struct LogMessage::LogMessageData {
LogMessageData(const LogMessageData&) = delete; LogMessageData(const LogMessageData&) = delete;
void operator=(const LogMessageData&) = delete; void operator=(const LogMessageData&) = delete;
}; };
} // namespace internal
} // namespace logging
// A mutex that allows only one thread to log at a time, to keep things from // A mutex that allows only one thread to log at a time, to keep things from
// getting jumbled. Some other very uncommon logging operations (like // getting jumbled. Some other very uncommon logging operations (like
@ -325,8 +328,7 @@ int64 LogMessage::num_messages_[NUM_SEVERITIES] = {0, 0, 0, 0};
// Globally disable log writing (if disk is full) // Globally disable log writing (if disk is full)
static bool stop_writing = false; static bool stop_writing = false;
const char* const LogSeverityNames[NUM_SEVERITIES] = {"INFO", "WARNING", const char* const LogSeverityNames[] = {"INFO", "WARNING", "ERROR", "FATAL"};
"ERROR", "FATAL"};
// Has the user called SetExitOnDFatal(true)? // Has the user called SetExitOnDFatal(true)?
static bool exit_on_dfatal = true; static bool exit_on_dfatal = true;
@ -547,7 +549,7 @@ class LogDestination {
// Wait for all registered sinks via WaitTillSent // Wait for all registered sinks via WaitTillSent
// including the optional one in "data". // including the optional one in "data".
static void WaitForSinks(LogMessage::LogMessageData* data); static void WaitForSinks(logging::internal::LogMessageData* data);
static LogDestination* log_destination(LogSeverity severity); static LogDestination* log_destination(LogSeverity severity);
@ -854,7 +856,8 @@ inline void LogDestination::LogToSinks(LogSeverity severity,
} }
} }
inline void LogDestination::WaitForSinks(LogMessage::LogMessageData* data) { inline void LogDestination::WaitForSinks(
logging::internal::LogMessageData* data) {
std::shared_lock<SinkMutex> l{sink_mutex_}; std::shared_lock<SinkMutex> l{sink_mutex_};
if (sinks_) { if (sinks_) {
for (size_t i = sinks_->size(); i-- > 0;) { for (size_t i = sinks_->size(); i-- > 0;) {
@ -1266,10 +1269,7 @@ void LogFileObject::Write(
uint32 this_drop_length = total_drop_length - dropped_mem_length_; uint32 this_drop_length = total_drop_length - dropped_mem_length_;
if (this_drop_length >= (2U << 20U)) { if (this_drop_length >= (2U << 20U)) {
// Only advise when >= 2MiB to drop // Only advise when >= 2MiB to drop
# if defined(__ANDROID__) && defined(__ANDROID_API__) && (__ANDROID_API__ < 21) # if defined(HAVE_POSIX_FADVISE)
// 'posix_fadvise' introduced in API 21:
// * https://android.googlesource.com/platform/bionic/+/6880f936173081297be0dc12f687d341b86a4cfa/libc/libc.map.txt#732
# else
posix_fadvise( posix_fadvise(
fileno(file_.get()), static_cast<off_t>(dropped_mem_length_), fileno(file_.get()), static_cast<off_t>(dropped_mem_length_),
static_cast<off_t>(this_drop_length), POSIX_FADV_DONTNEED); static_cast<off_t>(this_drop_length), POSIX_FADV_DONTNEED);
@ -1488,8 +1488,8 @@ bool LogCleaner::IsLogLastModifiedOver(
static std::mutex fatal_msg_lock; static std::mutex fatal_msg_lock;
static logging::internal::CrashReason crash_reason; static logging::internal::CrashReason crash_reason;
static bool fatal_msg_exclusive = true; static bool fatal_msg_exclusive = true;
static LogMessage::LogMessageData fatal_msg_data_exclusive; static logging::internal::LogMessageData fatal_msg_data_exclusive;
static LogMessage::LogMessageData fatal_msg_data_shared; static logging::internal::LogMessageData fatal_msg_data_shared;
#ifdef GLOG_THREAD_LOCAL_STORAGE #ifdef GLOG_THREAD_LOCAL_STORAGE
// Static thread-local log data space to use, because typically at most one // Static thread-local log data space to use, because typically at most one
@ -1499,16 +1499,16 @@ static thread_local bool thread_data_available = true;
# if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L # if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
// std::aligned_storage is deprecated in C++23 // std::aligned_storage is deprecated in C++23
alignas(LogMessage::LogMessageData) static thread_local std::byte alignas(logging::internal::LogMessageData) static thread_local std::byte
thread_msg_data[sizeof(LogMessage::LogMessageData)]; thread_msg_data[sizeof(logging::internal::LogMessageData)];
# else // !(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L) # else // !(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L)
static thread_local std::aligned_storage< static thread_local std::aligned_storage<
sizeof(LogMessage::LogMessageData), sizeof(logging::internal::LogMessageData),
alignof(LogMessage::LogMessageData)>::type thread_msg_data; alignof(logging::internal::LogMessageData)>::type thread_msg_data;
# endif // defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L # endif // defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
#endif // defined(GLOG_THREAD_LOCAL_STORAGE) #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
LogMessage::LogMessageData::LogMessageData() logging::internal::LogMessageData::LogMessageData()
: stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {} : stream_(message_text_, LogMessage::kMaxLogMessageLen, 0) {}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity, LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
@ -1518,7 +1518,8 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
data_->stream_.set_ctr(ctr); data_->stream_.set_ctr(ctr);
} }
LogMessage::LogMessage(const char* file, int line, const CheckOpString& result) LogMessage::LogMessage(const char* file, int line,
const logging::internal::CheckOpString& result)
: allocated_(nullptr) { : allocated_(nullptr) {
Init(file, line, GLOG_FATAL, &LogMessage::SendToLog); Init(file, line, GLOG_FATAL, &LogMessage::SendToLog);
stream() << "Check failed: " << (*result.str_) << " "; stream() << "Check failed: " << (*result.str_) << " ";
@ -1564,13 +1565,13 @@ void LogMessage::Init(const char* file, int line, LogSeverity severity,
// No need for locking, because this is thread local. // No need for locking, because this is thread local.
if (thread_data_available) { if (thread_data_available) {
thread_data_available = false; thread_data_available = false;
data_ = new (&thread_msg_data) LogMessageData; data_ = new (&thread_msg_data) logging::internal::LogMessageData;
} else { } else {
allocated_ = new LogMessageData(); allocated_ = new logging::internal::LogMessageData();
data_ = allocated_; data_ = allocated_;
} }
#else // !defined(GLOG_THREAD_LOCAL_STORAGE) #else // !defined(GLOG_THREAD_LOCAL_STORAGE)
allocated_ = new LogMessageData(); allocated_ = new logging::internal::LogMessageData();
data_ = allocated_; data_ = allocated_;
#endif // defined(GLOG_THREAD_LOCAL_STORAGE) #endif // defined(GLOG_THREAD_LOCAL_STORAGE)
data_->first_fatal_ = false; data_->first_fatal_ = false;
@ -1828,7 +1829,7 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
LogDestination::WaitForSinks(data_); LogDestination::WaitForSinks(data_);
const char* message = "*** Check failure stack trace: ***\n"; const char* message = "*** Check failure stack trace: ***\n";
if (write(STDERR_FILENO, message, strlen(message)) < 0) { if (write(fileno(stderr), message, strlen(message)) < 0) {
// Ignore errors. // Ignore errors.
} }
AlsoErrorWrite(GLOG_FATAL, AlsoErrorWrite(GLOG_FATAL,
@ -1856,7 +1857,7 @@ GLOG_NO_EXPORT logging_fail_func_t g_logging_fail_func =
NullStream::NullStream() : LogMessage::LogStream(message_buffer_, 2, 0) {} NullStream::NullStream() : LogMessage::LogStream(message_buffer_, 2, 0) {}
NullStream::NullStream(const char* /*file*/, int /*line*/, NullStream::NullStream(const char* /*file*/, int /*line*/,
const CheckOpString& /*result*/) const logging::internal::CheckOpString& /*result*/)
: LogMessage::LogStream(message_buffer_, 2, 0) {} : LogMessage::LogStream(message_buffer_, 2, 0) {}
NullStream& NullStream::stream() { return *this; } NullStream& NullStream::stream() { return *this; }
@ -2455,6 +2456,8 @@ void TruncateStdoutStderr() {
#endif #endif
} }
namespace logging {
namespace internal {
// Helper functions for string comparisons. // Helper functions for string comparisons.
#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \ #define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
string* Check##func##expected##Impl(const char* s1, const char* s2, \ string* Check##func##expected##Impl(const char* s1, const char* s2, \
@ -2475,6 +2478,8 @@ DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true) DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)
DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false) DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
#undef DEFINE_CHECK_STROP_IMPL #undef DEFINE_CHECK_STROP_IMPL
} // namespace internal
} // namespace logging
// glibc has traditionally implemented two incompatible versions of // glibc has traditionally implemented two incompatible versions of
// strerror_r(). There is a poorly defined convention for picking the // strerror_r(). There is a poorly defined convention for picking the
@ -2541,7 +2546,6 @@ int posix_strerror_r(int err, char* buf, size_t len) {
// A thread-safe replacement for strerror(). Returns a string describing the // A thread-safe replacement for strerror(). Returns a string describing the
// given POSIX error code. // given POSIX error code.
GLOG_NO_EXPORT
string StrError(int err) { string StrError(int err) {
char buf[100]; char buf[100];
int rc = posix_strerror_r(err, buf, sizeof(buf)); int rc = posix_strerror_r(err, buf, sizeof(buf));
@ -2555,7 +2559,7 @@ LogMessageFatal::LogMessageFatal(const char* file, int line)
: LogMessage(file, line, GLOG_FATAL) {} : LogMessage(file, line, GLOG_FATAL) {}
LogMessageFatal::LogMessageFatal(const char* file, int line, LogMessageFatal::LogMessageFatal(const char* file, int line,
const CheckOpString& result) const logging::internal::CheckOpString& result)
: LogMessage(file, line, result) {} : LogMessage(file, line, result) {}
LogMessageFatal::~LogMessageFatal() { LogMessageFatal::~LogMessageFatal() {
@ -2563,7 +2567,8 @@ LogMessageFatal::~LogMessageFatal() {
LogMessage::Fail(); LogMessage::Fail();
} }
namespace base { namespace logging {
namespace internal {
CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext)
: stream_(new ostringstream) { : stream_(new ostringstream) {
@ -2582,8 +2587,6 @@ string* CheckOpMessageBuilder::NewString() {
return new string(stream_->str()); return new string(stream_->str());
} }
} // namespace base
template <> template <>
void MakeCheckOpValueString(std::ostream* os, const char& v) { void MakeCheckOpValueString(std::ostream* os, const char& v) {
if (v >= 32 && v <= 126) { if (v >= 32 && v <= 126) {
@ -2616,9 +2619,10 @@ void MakeCheckOpValueString(std::ostream* os, const std::nullptr_t& /*v*/) {
(*os) << "nullptr"; (*os) << "nullptr";
} }
void InitGoogleLogging(const char* argv0) { } // namespace internal
glog_internal_namespace_::InitGoogleLoggingUtilities(argv0); } // namespace logging
}
void InitGoogleLogging(const char* argv0) { InitGoogleLoggingUtilities(argv0); }
void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback, void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback,
void* prefix_callback_data) { void* prefix_callback_data) {
@ -2628,7 +2632,7 @@ void InitGoogleLogging(const char* argv0, CustomPrefixCallback prefix_callback,
} }
void ShutdownGoogleLogging() { void ShutdownGoogleLogging() {
glog_internal_namespace_::ShutdownGoogleLoggingUtilities(); ShutdownGoogleLoggingUtilities();
LogDestination::DeleteLogDestinations(); LogDestination::DeleteLogDestinations();
logging_directories_list = nullptr; logging_directories_list = nullptr;
} }

View File

@ -61,6 +61,7 @@
#include "glog/logging.h" #include "glog/logging.h"
#include "glog/raw_logging.h" #include "glog/raw_logging.h"
#include "googletest.h" #include "googletest.h"
#include "stacktrace.h"
#include "utilities.h" #include "utilities.h"
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS

View File

@ -33,29 +33,18 @@
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <cstring>
#include <iomanip> #include <iomanip>
#include <mutex> #include <mutex>
#include <ostream> #include <ostream>
#include <streambuf> #include <streambuf>
#include <thread> #include <thread>
#include "utilities.h" #include "config.h"
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> // for close() and write() # include <unistd.h> // for close() and write()
#endif #endif
#include <fcntl.h> // for open()
#include <ctime>
#include "base/commandlineflags.h"
#include "config.h"
#include "glog/logging.h" // To pick up flag settings etc.
#include "glog/raw_logging.h"
#ifdef HAVE_STACKTRACE
# include "stacktrace.h"
#endif
#if defined(HAVE_SYSCALL_H) #if defined(HAVE_SYSCALL_H)
# include <syscall.h> // for syscall() # include <syscall.h> // for syscall()
#elif defined(HAVE_SYS_SYSCALL_H) #elif defined(HAVE_SYS_SYSCALL_H)
@ -64,6 +53,12 @@
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <fcntl.h> // for open()
#include "glog/logging.h"
#include "glog/raw_logging.h"
#include "stacktrace.h"
#include "utilities.h"
#if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \ #if (defined(HAVE_SYSCALL_H) || defined(HAVE_SYS_SYSCALL_H)) && \
(!(defined(GLOG_OS_MACOSX)) && !(defined(GLOG_OS_OPENBSD))) && \ (!(defined(GLOG_OS_MACOSX)) && !(defined(GLOG_OS_OPENBSD))) && \
@ -173,7 +168,7 @@ void RawLog__(LogSeverity severity, const char* file, int line,
// NOTE: this format should match the specification in base/logging.h // NOTE: this format should match the specification in base/logging.h
DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %s %s:%d] RAW: ", DoRawLog(&buf, &size, "%c00000000 00:00:00.000000 %s %s:%d] RAW: ",
LogSeverityNames[severity][0], sbuf.data(), GetLogSeverityName(severity)[0], sbuf.data(),
const_basename(const_cast<char*>(file)), line); const_basename(const_cast<char*>(file)), line);
// Record the position and size of the buffer after the prefix // Record the position and size of the buffer after the prefix
@ -193,7 +188,7 @@ void RawLog__(LogSeverity severity, const char* file, int line,
// avoiding FILE buffering (to avoid invoking malloc()), and bypassing // avoiding FILE buffering (to avoid invoking malloc()), and bypassing
// libc (to side-step any libc interception). // libc (to side-step any libc interception).
// We write just once to avoid races with other invocations of RawLog__. // We write just once to avoid races with other invocations of RawLog__.
safe_write(STDERR_FILENO, buffer, strlen(buffer)); safe_write(fileno(stderr), buffer, strlen(buffer));
if (severity == GLOG_FATAL) { if (severity == GLOG_FATAL) {
std::call_once(crashed, [file, line, msg_start, msg_size] { std::call_once(crashed, [file, line, msg_start, msg_size] {
crash_reason.filename = file; crash_reason.filename = file;

View File

@ -33,12 +33,15 @@
#include <algorithm> #include <algorithm>
#include <csignal> #include <csignal>
#include <cstring>
#include <ctime> #include <ctime>
#include <mutex> #include <mutex>
#include <sstream> #include <sstream>
#include <thread> #include <thread>
#include "config.h"
#include "glog/logging.h" #include "glog/logging.h"
#include "glog/platform.h"
#include "stacktrace.h" #include "stacktrace.h"
#include "symbolize.h" #include "symbolize.h"
#include "utilities.h" #include "utilities.h"
@ -155,7 +158,7 @@ class MinimalFormatter {
// Writes the given data with the size to the standard error. // Writes the given data with the size to the standard error.
void WriteToStderr(const char* data, size_t size) { void WriteToStderr(const char* data, size_t size) {
if (write(STDERR_FILENO, data, size) < 0) { if (write(fileno(stderr), data, size) < 0) {
// Ignore errors. // Ignore errors.
} }
} }
@ -231,6 +234,7 @@ void DumpSignalInfo(int signal_number, siginfo_t* siginfo) {
void DumpStackFrameInfo(const char* prefix, void* pc) { void DumpStackFrameInfo(const char* prefix, void* pc) {
// Get the symbol name. // Get the symbol name.
const char* symbol = "(unknown)"; const char* symbol = "(unknown)";
#if defined(HAVE_SYMBOLIZE)
char symbolized[1024]; // Big enough for a sane symbol. char symbolized[1024]; // Big enough for a sane symbol.
// Symbolizes the previous address of pc because pc may be in the // Symbolizes the previous address of pc because pc may be in the
// next function. // next function.
@ -238,6 +242,10 @@ void DumpStackFrameInfo(const char* prefix, void* pc) {
sizeof(symbolized))) { sizeof(symbolized))) {
symbol = symbolized; symbol = symbolized;
} }
#else
# pragma message( \
"Symbolize functionality is not available for target platform: stack dump will contain empty frames.")
#endif // defined(HAVE_SYMBOLIZE)
char buf[1024]; // Big enough for stack frame info. char buf[1024]; // Big enough for stack frame info.
MinimalFormatter formatter(buf, sizeof(buf)); MinimalFormatter formatter(buf, sizeof(buf));

View File

@ -39,13 +39,21 @@
#include <string> #include <string>
#include <thread> #include <thread>
#include "config.h"
#include "glog/logging.h" #include "glog/logging.h"
#include "utilities.h" #include "stacktrace.h"
#include "symbolize.h"
#if defined(HAVE_UNISTD_H)
# include <unistd.h>
#endif
#ifdef GLOG_USE_GFLAGS #ifdef GLOG_USE_GFLAGS
# include <gflags/gflags.h> # include <gflags/gflags.h>
using namespace GFLAGS_NAMESPACE; using namespace GFLAGS_NAMESPACE;
#endif #endif
#if defined(_MSC_VER)
# include <io.h> // write
#endif
using namespace google; using namespace google;
@ -59,7 +67,7 @@ static void DieInThread(int* a) {
} }
static void WriteToStdout(const char* data, size_t size) { static void WriteToStdout(const char* data, size_t size) {
if (write(STDOUT_FILENO, data, size) < 0) { if (write(fileno(stdout), data, size) < 0) {
// Ignore errors. // Ignore errors.
} }
} }

38
src/stacktrace.cc Normal file
View File

@ -0,0 +1,38 @@
// Copyright (c) 2024, 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.
//
// Routines to extract the current stack trace. These functions are
// thread-safe.
#include "stacktrace.h"
// Make an implementation of stacktrace compiled.
#if defined(STACKTRACE_H)
# include STACKTRACE_H
#endif

View File

@ -1,4 +1,4 @@
// Copyright (c) 2000 - 2007, Google Inc. // Copyright (c) 2024, Google Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -30,13 +30,46 @@
// Routines to extract the current stack trace. These functions are // Routines to extract the current stack trace. These functions are
// thread-safe. // thread-safe.
#ifndef BASE_STACKTRACE_H_ #ifndef GLOG_INTERNAL_STACKTRACE_H
#define BASE_STACKTRACE_H_ #define GLOG_INTERNAL_STACKTRACE_H
#include "glog/platform.h"
#if defined(GLOG_USE_GLOG_EXPORT)
# include "glog/export.h"
#endif
#if !defined(GLOG_NO_EXPORT)
# error "stacktrace.h" was not included correctly.
#endif
#include "config.h" #include "config.h"
#include "glog/logging.h" #if defined(HAVE_LIBUNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h"
#elif defined(HAVE_UNWIND)
# define STACKTRACE_H "stacktrace_unwind-inl.h"
#elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"
# elif defined(GLOG_OS_WINDOWS)
# define STACKTRACE_H "stacktrace_windows-inl.h"
# endif
#endif
#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE)
# define STACKTRACE_H "stacktrace_generic-inl.h"
#endif
#if defined(STACKTRACE_H)
# define HAVE_STACKTRACE
#endif
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
#if defined(HAVE_STACKTRACE)
// This is similar to the GetStackFrames routine, except that it returns // This is similar to the GetStackFrames routine, except that it returns
// the stack trace only, and not the stack frame sizes as well. // the stack trace only, and not the stack frame sizes as well.
@ -54,8 +87,11 @@ namespace google {
// .... ... // .... ...
// //
// "result" must not be nullptr. // "result" must not be nullptr.
GLOG_EXPORT int GetStackTrace(void** result, int max_depth, int skip_count); GLOG_NO_EXPORT int GetStackTrace(void** result, int max_depth, int skip_count);
#endif // defined(HAVE_STACKTRACE)
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
#endif // BASE_STACKTRACE_H_ #endif // GLOG_INTERNAL_STACKTRACE_H

View File

@ -38,6 +38,7 @@
#include "stacktrace.h" #include "stacktrace.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// If you change this function, also change GetStackFrames below. // If you change this function, also change GetStackFrames below.
int GetStackTrace(void** result, int max_depth, int skip_count) { int GetStackTrace(void** result, int max_depth, int skip_count) {
@ -61,4 +62,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
return result_count; return result_count;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -41,6 +41,7 @@ extern "C" {
#include "stacktrace.h" #include "stacktrace.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// Sometimes, we can try to get a stack trace from within a stack // Sometimes, we can try to get a stack trace from within a stack
// trace, because libunwind can call mmap (maybe indirectly via an // trace, because libunwind can call mmap (maybe indirectly via an
@ -90,4 +91,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
return n; return n;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -41,6 +41,7 @@
#include "stacktrace.h" #include "stacktrace.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// Given a pointer to a stack frame, locate and return the calling // Given a pointer to a stack frame, locate and return the calling
// stackframe, or return nullptr if no stackframe can be found. Perform sanity // stackframe, or return nullptr if no stackframe can be found. Perform sanity
@ -131,4 +132,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
return n; return n;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -41,8 +41,6 @@
# include <execinfo.h> # include <execinfo.h>
#endif #endif
using namespace google;
#ifdef HAVE_STACKTRACE #ifdef HAVE_STACKTRACE
// Obtain a backtrace, verify that the expected callers are present in the // Obtain a backtrace, verify that the expected callers are present in the
@ -132,7 +130,7 @@ static void ATTRIBUTE_NOINLINE CheckStackTraceLeaf() {
ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]); ADJUST_ADDRESS_RANGE_FROM_RA(&expected_range[1]);
INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]); INIT_ADDRESS_RANGE(CheckStackTraceLeaf, start, end, &expected_range[0]);
DECLARE_ADDRESS_LABEL(start); DECLARE_ADDRESS_LABEL(start);
size = GetStackTrace(stack, STACK_LEN, 0); size = google::GetStackTrace(stack, STACK_LEN, 0);
printf("Obtained %d stack frames.\n", size); printf("Obtained %d stack frames.\n", size);
CHECK_GE(size, 1); CHECK_GE(size, 1);
CHECK_LE(size, STACK_LEN); CHECK_LE(size, STACK_LEN);
@ -231,7 +229,7 @@ static
int main(int, char** argv) { int main(int, char** argv) {
FLAGS_logtostderr = true; FLAGS_logtostderr = true;
InitGoogleLogging(argv[0]); google::InitGoogleLogging(argv[0]);
CheckStackTrace(0); CheckStackTrace(0);

View File

@ -36,6 +36,7 @@
#include "stacktrace.h" #include "stacktrace.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
struct trace_arg_t { struct trace_arg_t {
void** result; void** result;
@ -101,4 +102,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
return targ.count; return targ.count;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -31,15 +31,13 @@
// //
// Windows implementation - just use CaptureStackBackTrace // Windows implementation - just use CaptureStackBackTrace
// clang-format off
#include <windows.h> // Must come before <dbghelp.h>
#include <dbghelp.h> #include <dbghelp.h>
// clang-format on
#include "config.h"
#if defined(GLOG_USE_WINDOWS_PORT)
# include "port.h"
#endif
#include "stacktrace.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
int GetStackTrace(void** result, int max_depth, int skip_count) { int GetStackTrace(void** result, int max_depth, int skip_count) {
if (max_depth > 64) { if (max_depth > 64) {
@ -51,4 +49,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
static_cast<DWORD>(max_depth), result, nullptr); static_cast<DWORD>(max_depth), result, nullptr);
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -43,6 +43,7 @@
#include "stacktrace.h" #include "stacktrace.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// Given a pointer to a stack frame, locate and return the calling // Given a pointer to a stack frame, locate and return the calling
// stackframe, or return nullptr if no stackframe can be found. Perform sanity // stackframe, or return nullptr if no stackframe can be found. Perform sanity
@ -155,5 +156,5 @@ int GetStackTrace(void** result, int max_depth, int skip_count) {
} }
return n; return n;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google

View File

@ -71,6 +71,7 @@
# define GLOG_SAFE_ASSERT(expr) ((expr) ? 0 : (std::abort(), 0)) # define GLOG_SAFE_ASSERT(expr) ((expr) ? 0 : (std::abort(), 0))
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
namespace { namespace {
@ -105,6 +106,7 @@ void InstallSymbolizeOpenObjectFileCallback(
g_symbolize_open_object_file_callback = callback; g_symbolize_open_object_file_callback = callback;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
# if defined(__ELF__) # if defined(__ELF__)
@ -135,6 +137,7 @@ void InstallSymbolizeOpenObjectFileCallback(
# include "symbolize.h" # include "symbolize.h"
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
namespace { namespace {
@ -822,6 +825,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(
return true; return true;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR) # elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
@ -831,6 +835,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(
# include <cstring> # include <cstring>
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle( static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(
void* pc, char* out, size_t out_size, SymbolizeOptions /*options*/) { void* pc, char* out, size_t out_size, SymbolizeOptions /*options*/) {
@ -848,6 +853,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(
return false; return false;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
# elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN) # elif defined(GLOG_OS_WINDOWS) || defined(GLOG_OS_CYGWIN)
@ -856,6 +862,9 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(
# include <windows.h> # include <windows.h>
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
namespace {
class SymInitializer final { class SymInitializer final {
public: public:
@ -883,6 +892,8 @@ class SymInitializer final {
SymInitializer& operator=(SymInitializer&&) = delete; SymInitializer& operator=(SymInitializer&&) = delete;
}; };
} // namespace
static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out, static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
size_t out_size, size_t out_size,
SymbolizeOptions options) { SymbolizeOptions options) {
@ -942,6 +953,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
return false; return false;
} }
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
# else # else
@ -949,28 +961,13 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void* pc, char* out,
# endif # endif
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
bool Symbolize(void* pc, char* out, size_t out_size, SymbolizeOptions options) { bool Symbolize(void* pc, char* out, size_t out_size, SymbolizeOptions options) {
return SymbolizeAndDemangle(pc, out, out_size, options); return SymbolizeAndDemangle(pc, out, out_size, options);
} }
} // namespace google } // namespace glog_internal_namespace_
#else /* HAVE_SYMBOLIZE */
# include <cassert>
# include "config.h"
namespace google {
// TODO: Support other environments.
bool Symbolize(void* /*pc*/, char* /*out*/, size_t /*out_size*/,
SymbolizeOptions /*options*/) {
assert(0);
return false;
}
} // namespace google } // namespace google
#endif #endif

View File

@ -51,14 +51,38 @@
// malloc() and other unsafe operations. It should be both // malloc() and other unsafe operations. It should be both
// thread-safe and async-signal-safe. // thread-safe and async-signal-safe.
#ifndef BASE_SYMBOLIZE_H_ #ifndef GLOG_INTERNAL_SYMBOLIZE_H
#define BASE_SYMBOLIZE_H_ #define GLOG_INTERNAL_SYMBOLIZE_H
#include <cstddef>
#include <cstdint>
#include <type_traits> #include <type_traits>
#include "config.h" #include "config.h"
#include "glog/logging.h" #include "glog/platform.h"
#include "utilities.h"
#if defined(GLOG_USE_GLOG_EXPORT)
# include "glog/export.h"
#endif
#if !defined(GLOG_NO_EXPORT)
# error "symbolize.h" was not included correctly.
#endif
#ifndef GLOG_NO_SYMBOLIZE_DETECTION
# ifndef HAVE_SYMBOLIZE
// defined by gcc
# if defined(__ELF__) && defined(GLOG_OS_LINUX)
# define HAVE_SYMBOLIZE
# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
// Use dladdr to symbolize.
# define HAVE_SYMBOLIZE
# elif defined(GLOG_OS_WINDOWS)
// Use DbgHelp to symbolize
# define HAVE_SYMBOLIZE
# endif
# endif // !defined(HAVE_SYMBOLIZE)
#endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION)
#ifdef HAVE_SYMBOLIZE #ifdef HAVE_SYMBOLIZE
@ -69,7 +93,7 @@
# include <elf.h> # include <elf.h>
# endif # endif
# if !defined(ANDROID) # if !defined(GLOG_OS_ANDROID)
# include <link.h> // For ElfW() macro. # include <link.h> // For ElfW() macro.
# endif # endif
@ -95,17 +119,21 @@
# endif # endif
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// Gets the section header for the given name, if it exists. Returns true on // Gets the section header for the given name, if it exists. Returns true on
// success. Otherwise, returns false. // success. Otherwise, returns false.
GLOG_NO_EXPORT
bool GetSectionHeaderByName(int fd, const char* name, size_t name_len, bool GetSectionHeaderByName(int fd, const char* name, size_t name_len,
ElfW(Shdr) * out); ElfW(Shdr) * out);
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
# endif /* __ELF__ */ # endif /* __ELF__ */
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
// Restrictions on the callbacks that follow: // Restrictions on the callbacks that follow:
// - The callbacks must not use heaps but only use stacks. // - The callbacks must not use heaps but only use stacks.
@ -119,7 +147,7 @@ namespace google {
// and return the size of the output written. On error, the callback // and return the size of the output written. On error, the callback
// function should return -1. // function should return -1.
using SymbolizeCallback = int (*)(int, void*, char*, size_t, uint64_t); using SymbolizeCallback = int (*)(int, void*, char*, size_t, uint64_t);
GLOG_EXPORT GLOG_NO_EXPORT
void InstallSymbolizeCallback(SymbolizeCallback callback); void InstallSymbolizeCallback(SymbolizeCallback callback);
// Installs a callback function, which will be called instead of // Installs a callback function, which will be called instead of
@ -134,15 +162,19 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
// (including the null-terminator). // (including the null-terminator).
using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&, using SymbolizeOpenObjectFileCallback = int (*)(uint64_t, uint64_t&, uint64_t&,
char*, size_t); char*, size_t);
GLOG_EXPORT GLOG_NO_EXPORT
void InstallSymbolizeOpenObjectFileCallback( void InstallSymbolizeOpenObjectFileCallback(
SymbolizeOpenObjectFileCallback callback); SymbolizeOpenObjectFileCallback callback);
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
#endif #endif
namespace google { namespace google {
inline namespace glog_internal_namespace_ {
#if defined(HAVE_SYMBOLIZE)
enum class SymbolizeOptions { enum class SymbolizeOptions {
// No additional options. // No additional options.
@ -169,9 +201,13 @@ constexpr SymbolizeOptions operator|(SymbolizeOptions lhs,
// symbol name to "out". The symbol name is demangled if possible // symbol name to "out". The symbol name is demangled if possible
// (supports symbols generated by GCC 3.x or newer). Otherwise, // (supports symbols generated by GCC 3.x or newer). Otherwise,
// returns false. // returns false.
GLOG_EXPORT bool Symbolize(void* pc, char* out, size_t out_size, GLOG_NO_EXPORT bool Symbolize(
void* pc, char* out, size_t out_size,
SymbolizeOptions options = SymbolizeOptions::kNone); SymbolizeOptions options = SymbolizeOptions::kNone);
#endif // defined(HAVE_SYMBOLIZE)
} // namespace glog_internal_namespace_
} // namespace google } // namespace google
#endif // BASE_SYMBOLIZE_H_ #endif // GLOG_INTERNAL_SYMBOLIZE_H

View File

@ -41,8 +41,12 @@
#include "base/googleinit.h" #include "base/googleinit.h"
#include "config.h" #include "config.h"
#include "glog/flags.h"
#include "glog/logging.h"
#include "stacktrace.h"
#include "symbolize.h"
#ifdef __ANDROID__ #ifdef GLOG_OS_ANDROID
# include <android/log.h> # include <android/log.h>
#endif #endif
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
@ -88,7 +92,7 @@ void AlsoErrorWrite(LogSeverity severity, const char* tag,
(void)tag; (void)tag;
// On Windows, also output to the debugger // On Windows, also output to the debugger
::OutputDebugStringA(message); ::OutputDebugStringA(message);
#elif defined(__ANDROID__) #elif defined(GLOG_OS_ANDROID)
constexpr int android_log_levels[] = { constexpr int android_log_levels[] = {
ANDROID_LOG_INFO, ANDROID_LOG_INFO,
ANDROID_LOG_WARN, ANDROID_LOG_WARN,
@ -125,7 +129,7 @@ static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
static void DebugWriteToStderr(const char* data, void*) { static void DebugWriteToStderr(const char* data, void*) {
// This one is signal-safe. // This one is signal-safe.
if (write(STDERR_FILENO, data, strlen(data)) < 0) { if (write(fileno(stderr), data, strlen(data)) < 0) {
// Ignore errors. // Ignore errors.
} }
AlsoErrorWrite(GLOG_FATAL, AlsoErrorWrite(GLOG_FATAL,
@ -319,18 +323,4 @@ void ShutdownGoogleLoggingUtilities() {
} }
} // namespace glog_internal_namespace_ } // namespace glog_internal_namespace_
} // namespace google } // namespace google
// Make an implementation of stacktrace compiled.
#ifdef STACKTRACE_H
# include STACKTRACE_H
# if 0
// For include scanners which can't handle macro expansions.
# include "stacktrace_generic-inl.h"
# include "stacktrace_libunwind-inl.h"
# include "stacktrace_powerpc-inl.h"
# include "stacktrace_x86-inl.h"
# include "stacktrace_x86_64-inl.h"
# endif
#endif

View File

@ -32,8 +32,8 @@
// //
// Define utilities for glog internal usage. // Define utilities for glog internal usage.
#ifndef UTILITIES_H__ #ifndef GLOG_INTERNAL_UTILITIES_H
#define UTILITIES_H__ #define GLOG_INTERNAL_UTILITIES_H
#include <cstddef> #include <cstddef>
#include <cstdio> #include <cstdio>
@ -60,18 +60,14 @@
#define PRIXS __PRIS_PREFIX "X" #define PRIXS __PRIS_PREFIX "X"
#define PRIoS __PRIS_PREFIX "o" #define PRIoS __PRIS_PREFIX "o"
#include "glog/logging.h" #include "config.h"
#include "glog/platform.h"
#if defined(GLOG_USE_WINDOWS_PORT) #if defined(GLOG_USE_WINDOWS_PORT)
# include "port.h" # include "port.h"
#endif #endif
#include "config.h"
#if defined(HAVE_UNISTD_H) #if defined(HAVE_UNISTD_H)
# include <unistd.h> # include <unistd.h>
#endif #endif
#if !defined(HAVE_SSIZE_T) #if !defined(HAVE_SSIZE_T)
# if defined(GLOG_OS_WINDOWS) # if defined(GLOG_OS_WINDOWS)
# include <basetsd.h> # include <basetsd.h>
@ -81,6 +77,9 @@ using ssize_t = std::ptrdiff_t;
# endif # endif
#endif #endif
#include "glog/log_severity.h"
#include "glog/types.h"
// There are three different ways we can try to get the stack trace: // There are three different ways we can try to get the stack trace:
// //
// 1) The libunwind library. This is still in development, and as a // 1) The libunwind library. This is still in development, and as a
@ -103,43 +102,6 @@ using ssize_t = std::ptrdiff_t;
// correctly when GetStackTrace() is called with max_depth == 0. // correctly when GetStackTrace() is called with max_depth == 0.
// Some code may do that. // Some code may do that.
#if defined(HAVE_LIBUNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h"
#elif defined(HAVE_UNWIND)
# define STACKTRACE_H "stacktrace_unwind-inl.h"
#elif !defined(NO_FRAME_POINTER)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
# elif (defined(__ppc__) || defined(__PPC__)) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_powerpc-inl.h"
# elif defined(GLOG_OS_WINDOWS)
# define STACKTRACE_H "stacktrace_windows-inl.h"
# endif
#endif
#if !defined(STACKTRACE_H) && defined(HAVE_EXECINFO_BACKTRACE)
# define STACKTRACE_H "stacktrace_generic-inl.h"
#endif
#if defined(STACKTRACE_H)
# define HAVE_STACKTRACE
#endif
#ifndef GLOG_NO_SYMBOLIZE_DETECTION
# ifndef HAVE_SYMBOLIZE
// defined by gcc
# if defined(__ELF__) && defined(GLOG_OS_LINUX)
# define HAVE_SYMBOLIZE
# elif defined(GLOG_OS_MACOSX) && defined(HAVE_DLADDR)
// Use dladdr to symbolize.
# define HAVE_SYMBOLIZE
# elif defined(GLOG_OS_WINDOWS)
// Use DbgHelp to symbolize
# define HAVE_SYMBOLIZE
# endif
# endif // !defined(HAVE_SYMBOLIZE)
#endif // !defined(GLOG_NO_SYMBOLIZE_DETECTION)
#ifndef ARRAYSIZE #ifndef ARRAYSIZE
// There is a better way, but this is good enough for our purpose. // There is a better way, but this is good enough for our purpose.
# define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a))) # define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
@ -320,4 +282,4 @@ struct std::default_delete<std::FILE> {
void operator()(FILE* p) const noexcept { fclose(p); } void operator()(FILE* p) const noexcept { fclose(p); }
}; };
#endif // UTILITIES_H__ #endif // GLOG_INTERNAL_UTILITIES_H

View File

@ -1,4 +1,4 @@
// Copyright (c) 1999, 2007, Google Inc. // Copyright (c) 2024, Google Inc.
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -39,9 +39,7 @@
#include <mutex> #include <mutex>
#include <string> #include <string>
#include "glog/logging.h"
#include "glog/raw_logging.h" #include "glog/raw_logging.h"
#include "utilities.h"
// glog doesn't have annotation // glog doesn't have annotation
#define ANNOTATE_BENIGN_RACE(address, description) #define ANNOTATE_BENIGN_RACE(address, description)

View File

@ -6,8 +6,8 @@
* under the MIT license. For all details and documentation, see * under the MIT license. For all details and documentation, see
* https://github.com/tronkko/dirent * https://github.com/tronkko/dirent
*/ */
#ifndef DIRENT_H #ifndef GLOG_INTERNAL_WINDOWS_DIRENT_H
#define DIRENT_H #define GLOG_INTERNAL_WINDOWS_DIRENT_H
/* Hide warnings about unreferenced local functions */ /* Hide warnings about unreferenced local functions */
#if defined(__clang__) #if defined(__clang__)
@ -1037,4 +1037,4 @@ static void dirent_set_errno(int error) {
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /*DIRENT_H*/ #endif /*GLOG_INTERNAL_WINDOWS_DIRENT_H*/

View File

@ -42,6 +42,9 @@
#include "config.h" #include "config.h"
namespace google {
inline namespace glog_internal_namespace_ {
#ifndef HAVE_LOCALTIME_R #ifndef HAVE_LOCALTIME_R
struct tm* localtime_r(const std::time_t* timep, std::tm* result) { struct tm* localtime_r(const std::time_t* timep, std::tm* result) {
localtime_s(result, timep); localtime_s(result, timep);
@ -54,3 +57,6 @@ struct tm* gmtime_r(const std::time_t* timep, std::tm* result) {
return result; return result;
} }
#endif // not HAVE_GMTIME_R #endif // not HAVE_GMTIME_R
} // namespace glog_internal_namespace_
} // namespace google

View File

@ -43,6 +43,14 @@
#include "config.h" #include "config.h"
#if defined(GLOG_USE_GLOG_EXPORT)
# include "glog/export.h"
#endif
#if !defined(GLOG_EXPORT)
# error "port.h" was not included correctly.
#endif
#ifdef _WIN32 #ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN # ifndef WIN32_LEAN_AND_MEAN
@ -62,8 +70,6 @@
* used by both C and C++ code, so we put all the C++ together. * used by both C and C++ code, so we put all the C++ together.
*/ */
# include "glog/logging.h"
# ifdef _MSC_VER # ifdef _MSC_VER
/* 4244: otherwise we get problems when substracting two size_t's to an int /* 4244: otherwise we get problems when substracting two size_t's to an int
@ -89,9 +95,6 @@
# define O_CREAT _O_CREAT # define O_CREAT _O_CREAT
# define O_EXCL _O_EXCL # define O_EXCL _O_EXCL
# ifndef __MINGW32__
enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
# endif
# define S_IRUSR S_IREAD # define S_IRUSR S_IREAD
# define S_IWUSR S_IWRITE # define S_IWUSR S_IWRITE
@ -116,24 +119,23 @@ enum { STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2 };
# endif // _MSC_VER # endif // _MSC_VER
namespace google {
inline namespace glog_internal_namespace_ {
# ifndef HAVE_LOCALTIME_R # ifndef HAVE_LOCALTIME_R
extern GLOG_EXPORT std::tm* localtime_r(const std::time_t* timep, GLOG_NO_EXPORT std::tm* localtime_r(const std::time_t* timep, std::tm* result);
std::tm* result);
# endif // not HAVE_LOCALTIME_R # endif // not HAVE_LOCALTIME_R
# ifndef HAVE_GMTIME_R # ifndef HAVE_GMTIME_R
extern GLOG_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result); GLOG_NO_EXPORT std::tm* gmtime_r(const std::time_t* timep, std::tm* result);
# endif // not HAVE_GMTIME_R # endif // not HAVE_GMTIME_R
GLOG_NO_EXPORT
inline char* strerror_r(int errnum, char* buf, std::size_t buflen) { inline char* strerror_r(int errnum, char* buf, std::size_t buflen) {
strerror_s(buf, buflen, errnum); strerror_s(buf, buflen, errnum);
return buf; return buf;
} }
} // namespace glog_internal_namespace_
# ifndef __cplusplus } // namespace google
/* I don't see how to get inlining for C code in MSVC. Ah well. */
# define inline
# endif
#endif /* _WIN32 */ #endif /* _WIN32 */