1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_
6 #define PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_
7
8 #include <cstddef>
9
10 #include "build/build_config.h"
11 #include "partition_alloc/partition_alloc_base/component_export.h"
12 #include "partition_alloc/partition_alloc_base/debug/debugging_buildflags.h"
13 #include "partition_alloc/partition_alloc_base/scoped_clear_last_error.h"
14 #include "partition_alloc/partition_alloc_base/strings/cstring_builder.h"
15
16 namespace partition_alloc::internal::logging {
17
18 // Sets the Log Message Handler that gets passed every log message before
19 // it's sent to other log destinations (if any).
20 // Returns true to signal that it handled the message and the message
21 // should not be sent to other log destinations.
22 typedef bool (*LogMessageHandlerFunction)(int severity,
23 const char* file,
24 int line,
25 size_t message_start,
26 const char* str);
27 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
28 void SetLogMessageHandler(LogMessageHandlerFunction handler);
29 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
30 LogMessageHandlerFunction GetLogMessageHandler();
31
32 using LogSeverity = int;
33 constexpr LogSeverity LOGGING_VERBOSE = -1; // This is level 1 verbosity
34 // Note: the log severities are used to index into the array of names,
35 // see log_severity_names.
36 constexpr LogSeverity LOGGING_INFO = 0;
37 constexpr LogSeverity LOGGING_WARNING = 1;
38 constexpr LogSeverity LOGGING_ERROR = 2;
39 constexpr LogSeverity LOGGING_FATAL = 3;
40 constexpr LogSeverity LOGGING_NUM_SEVERITIES = 4;
41
42 // LOGGING_DFATAL is LOGGING_FATAL in DCHECK-enabled builds, ERROR in normal
43 // mode.
44 #if BUILDFLAG(PA_DCHECK_IS_ON)
45 constexpr LogSeverity LOGGING_DFATAL = LOGGING_FATAL;
46 #else
47 constexpr LogSeverity LOGGING_DFATAL = LOGGING_ERROR;
48 #endif
49
50 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
51 extern base::strings::CStringBuilder* g_swallow_stream;
52
53 // This class more or less represents a particular log message. You
54 // create an instance of LogMessage and then stream stuff to it.
55 // When you finish streaming to it, ~LogMessage is called and the
56 // full message gets streamed to the appropriate destination.
57 //
58 // You shouldn't actually use LogMessage's constructor to log things,
59 // though. You should use the PA_LOG() macro (and variants thereof)
60 // above.
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)61 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) LogMessage {
62 public:
63 // Used for PA_LOG(severity).
64 LogMessage(const char* file, int line, LogSeverity severity);
65
66 // Used for CHECK(). Implied severity = LOGGING_FATAL.
67 LogMessage(const char* file, int line, const char* condition);
68 LogMessage(const LogMessage&) = delete;
69 LogMessage& operator=(const LogMessage&) = delete;
70 virtual ~LogMessage();
71
72 base::strings::CStringBuilder& stream() { return stream_; }
73
74 LogSeverity severity() { return severity_; }
75 const char* c_str() { return stream_.c_str(); }
76
77 private:
78 void Init(const char* file, int line);
79
80 const LogSeverity severity_;
81 base::strings::CStringBuilder stream_;
82 size_t message_start_; // Offset of the start of the message (past prefix
83 // info).
84 // The file and line information passed in to the constructor.
85 const char* const file_;
86 const int line_;
87
88 // This is useful since the LogMessage class uses a lot of Win32 calls
89 // that will lose the value of GLE and the code that called the log function
90 // will have lost the thread error value when the log call returns.
91 base::ScopedClearLastError last_error_;
92 };
93
94 // This class is used to explicitly ignore values in the conditional
95 // logging macros. This avoids compiler warnings like "value computed
96 // is not used" and "statement has no effect".
97 class LogMessageVoidify {
98 public:
99 LogMessageVoidify() = default;
100 // This has to be an operator with a precedence lower than << but
101 // higher than ?:
102 void operator&(base::strings::CStringBuilder&) {}
103 };
104
105 #if BUILDFLAG(IS_WIN)
106 typedef unsigned long SystemErrorCode;
107 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
108 typedef int SystemErrorCode;
109 #endif
110
111 // Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
112 // pull in windows.h just for GetLastError() and DWORD.
113 PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)
114 SystemErrorCode GetLastSystemErrorCode();
115
116 #if BUILDFLAG(IS_WIN)
117 // Appends a formatted system message of the GetLastError() type.
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)118 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) Win32ErrorLogMessage
119 : public LogMessage {
120 public:
121 Win32ErrorLogMessage(const char* file,
122 int line,
123 LogSeverity severity,
124 SystemErrorCode err);
125 Win32ErrorLogMessage(const Win32ErrorLogMessage&) = delete;
126 Win32ErrorLogMessage& operator=(const Win32ErrorLogMessage&) = delete;
127 // Appends the error message before destructing the encapsulated class.
128 ~Win32ErrorLogMessage() override;
129
130 private:
131 SystemErrorCode err_;
132 };
133 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
134 // Appends a formatted system message of the errno type
PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE)135 class PA_COMPONENT_EXPORT(PARTITION_ALLOC_BASE) ErrnoLogMessage
136 : public LogMessage {
137 public:
138 ErrnoLogMessage(const char* file,
139 int line,
140 LogSeverity severity,
141 SystemErrorCode err);
142 ErrnoLogMessage(const ErrnoLogMessage&) = delete;
143 ErrnoLogMessage& operator=(const ErrnoLogMessage&) = delete;
144 // Appends the error message before destructing the encapsulated class.
145 ~ErrnoLogMessage() override;
146
147 private:
148 SystemErrorCode err_;
149 };
150 #endif // BUILDFLAG(IS_WIN)
151
152 } // namespace partition_alloc::internal::logging
153
154 #endif // PARTITION_ALLOC_PARTITION_ALLOC_BASE_LOG_MESSAGE_H_
155