Skip to content

Commit 934d1de

Browse files
birenroycopybara-github
authored andcommitted
Automated g4 rollback of changelist 713678123.
*** Reason for rollback *** Rolling forward cl/712628602 with fixes. ``` $ blaze --blazerc=/dev/null test //vr/c9/client/ar:c9_ar_app_test_x86 \ --compilation_mode=opt --//third_party/android/ndk:min_sdk_version=28 \ --define=PORTABLE_PROTO_TRANSITION_MODE=google3 --config=android_x86 ``` http://sponge2/c3559a90-3f60-4b9b-9c86-af9cc8183953 *** Original change description *** Automated g4 rollback of changelist 712628602. *** Reason for rollback *** Breaks TAP project vr.c9.unit.android.x86 *** Original change description *** Moves the generic bug utility to QUICHE. *** *** PiperOrigin-RevId: 713703088
1 parent 7118deb commit 934d1de

File tree

7 files changed

+468
-0
lines changed

7 files changed

+468
-0
lines changed

build/source_list.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ protobuf_test_support = [
1010
]
1111
quiche_core_hdrs = [
1212
"common/btree_scheduler.h",
13+
"common/bug_utils.h",
14+
"common/bug_utils_test_helper.h",
1315
"common/capsule.h",
1416
"common/http/http_header_block.h",
1517
"common/http/http_header_storage.h",
@@ -409,6 +411,7 @@ quiche_core_hdrs = [
409411
"web_transport/web_transport_priority_scheduler.h",
410412
]
411413
quiche_core_srcs = [
414+
"common/bug_utils.cc",
412415
"common/capsule.cc",
413416
"common/http/http_header_block.cc",
414417
"common/http/http_header_storage.cc",
@@ -1077,6 +1080,7 @@ quiche_tests_srcs = [
10771080
"balsa/simple_buffer_test.cc",
10781081
"binary_http/binary_http_message_test.cc",
10791082
"common/btree_scheduler_test.cc",
1083+
"common/bug_utils_test.cc",
10801084
"common/capsule_test.cc",
10811085
"common/http/http_header_block_test.cc",
10821086
"common/http/http_header_storage_test.cc",

build/source_list.gni

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ protobuf_test_support = [
1010
]
1111
quiche_core_hdrs = [
1212
"src/quiche/common/btree_scheduler.h",
13+
"src/quiche/common/bug_utils.h",
14+
"src/quiche/common/bug_utils_test_helper.h",
1315
"src/quiche/common/capsule.h",
1416
"src/quiche/common/http/http_header_block.h",
1517
"src/quiche/common/http/http_header_storage.h",
@@ -409,6 +411,7 @@ quiche_core_hdrs = [
409411
"src/quiche/web_transport/web_transport_priority_scheduler.h",
410412
]
411413
quiche_core_srcs = [
414+
"src/quiche/common/bug_utils.cc",
412415
"src/quiche/common/capsule.cc",
413416
"src/quiche/common/http/http_header_block.cc",
414417
"src/quiche/common/http/http_header_storage.cc",
@@ -1078,6 +1081,7 @@ quiche_tests_srcs = [
10781081
"src/quiche/balsa/simple_buffer_test.cc",
10791082
"src/quiche/binary_http/binary_http_message_test.cc",
10801083
"src/quiche/common/btree_scheduler_test.cc",
1084+
"src/quiche/common/bug_utils_test.cc",
10811085
"src/quiche/common/capsule_test.cc",
10821086
"src/quiche/common/http/http_header_block_test.cc",
10831087
"src/quiche/common/http/http_header_storage_test.cc",

build/source_list.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
],
1010
"quiche_core_hdrs": [
1111
"quiche/common/btree_scheduler.h",
12+
"quiche/common/bug_utils.h",
13+
"quiche/common/bug_utils_test_helper.h",
1214
"quiche/common/capsule.h",
1315
"quiche/common/http/http_header_block.h",
1416
"quiche/common/http/http_header_storage.h",
@@ -408,6 +410,7 @@
408410
"quiche/web_transport/web_transport_priority_scheduler.h"
409411
],
410412
"quiche_core_srcs": [
413+
"quiche/common/bug_utils.cc",
411414
"quiche/common/capsule.cc",
412415
"quiche/common/http/http_header_block.cc",
413416
"quiche/common/http/http_header_storage.cc",
@@ -1077,6 +1080,7 @@
10771080
"quiche/balsa/simple_buffer_test.cc",
10781081
"quiche/binary_http/binary_http_message_test.cc",
10791082
"quiche/common/btree_scheduler_test.cc",
1083+
"quiche/common/bug_utils_test.cc",
10801084
"quiche/common/capsule_test.cc",
10811085
"quiche/common/http/http_header_block_test.cc",
10821086
"quiche/common/http/http_header_storage_test.cc",

quiche/common/bug_utils.cc

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include "quiche/common/bug_utils.h"
2+
3+
#include <atomic>
4+
#include <cstdint>
5+
#include <limits>
6+
#include <string>
7+
8+
#include "absl/base/log_severity.h"
9+
#include "absl/strings/str_cat.h"
10+
#include "absl/strings/string_view.h"
11+
12+
namespace quiche {
13+
namespace internal {
14+
15+
GenericBugStreamHandler::GenericBugStreamHandler(
16+
const char* prefix, const char* bug_id, const GenericBugOptions& options)
17+
: bug_id_(bug_id), options_(options) {
18+
if (options_.condition_str.empty()) {
19+
absl::StrAppend(&str_, prefix, "(", bug_id, "): ");
20+
} else {
21+
absl::StrAppend(&str_, prefix, "_IF(", bug_id, ", ", options_.condition_str,
22+
"): ");
23+
}
24+
}
25+
26+
GenericBugStreamHandler::~GenericBugStreamHandler() {
27+
GenericBugStreamHandler::OverrideFunction override_function =
28+
GetOverrideFunction();
29+
if (options_.bug_listener != nullptr) {
30+
options_.bug_listener->OnBug(bug_id_, options_.file_name, options_.line,
31+
str_);
32+
}
33+
if (override_function != nullptr) {
34+
override_function(options_.severity, options_.file_name, options_.line,
35+
str_);
36+
}
37+
}
38+
39+
// static
40+
void GenericBugStreamHandler::SetOverrideFunction(
41+
GenericBugStreamHandler::OverrideFunction override_function) {
42+
atomic_override_function_.store(override_function);
43+
}
44+
45+
// static
46+
GenericBugStreamHandler::OverrideFunction
47+
GenericBugStreamHandler::GetOverrideFunction() {
48+
return atomic_override_function_.load(std::memory_order_relaxed);
49+
}
50+
51+
// static
52+
std::atomic<GenericBugStreamHandler::OverrideFunction>
53+
GenericBugStreamHandler::atomic_override_function_ = nullptr;
54+
55+
void GenericBugWithoutLog(const char* bug_id,
56+
const GenericBugOptions& options) {
57+
if (options.bug_listener != nullptr) {
58+
options.bug_listener->OnBug(bug_id, options.file_name, options.line,
59+
/*No bug message*/ "");
60+
}
61+
}
62+
63+
} // namespace internal
64+
} // namespace quiche

quiche/common/bug_utils.h

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#ifndef QUICHE_COMMON_BUG_UTILS_H_
2+
#define QUICHE_COMMON_BUG_UTILS_H_
3+
4+
// This file contains macros for emitting bug log events when invariants are
5+
// violated.
6+
//
7+
// Each instance of a QUICHE_BUG and friends has an associated id, which can be
8+
// helpful for quickly finding the associated source code.
9+
//
10+
// The IDs are free form, but are expected to be unique. Best practice is to
11+
// provide a *short* description of the condition being detected, without
12+
// quotes, e.g.,
13+
//
14+
// QUICHE_BUG(http2_decoder_invalid_parse_state) << "...";
15+
//
16+
// QUICHE_BUG is defined in platform/api/quiche_bug_tracker.h.
17+
//
18+
19+
#include <atomic>
20+
#include <cstdint>
21+
#include <sstream>
22+
#include <string>
23+
#include <tuple>
24+
#include <type_traits>
25+
26+
#include "absl/base/log_severity.h"
27+
#include "absl/strings/str_cat.h"
28+
#include "absl/strings/string_view.h"
29+
#include "quiche/common/platform/api/quiche_export.h"
30+
31+
namespace quiche {
32+
namespace internal {
33+
34+
class QUICHE_EXPORT GenericBugListener {
35+
public:
36+
virtual ~GenericBugListener() = default;
37+
virtual void OnBug(const char* bug_id, const char* file, int line,
38+
absl::string_view bug_message) = 0;
39+
};
40+
41+
struct QUICHE_NO_EXPORT GenericBugOptions {
42+
explicit GenericBugOptions(absl::LogSeverity log_severity,
43+
const char* file_name, int line)
44+
: severity(log_severity), file_name(file_name), line(line) {}
45+
46+
GenericBugOptions& SetCondition(absl::string_view condition) {
47+
this->condition_str = condition;
48+
return *this;
49+
}
50+
51+
GenericBugOptions& SetBugListener(GenericBugListener* listener) {
52+
this->bug_listener = listener;
53+
return *this;
54+
}
55+
56+
absl::LogSeverity severity;
57+
const char* const file_name;
58+
const int line;
59+
// !empty() for conditional GENERIC_BUGs.
60+
absl::string_view condition_str;
61+
// If not nullptr, |bug_listener| will be notified of this GENERIC_BUG hit.
62+
// Since GenericBugListener may be a temporary object, this is only safe to
63+
// access from GenericBugStreamHandler, whose scope is strictly narrower.
64+
GenericBugListener* bug_listener = nullptr;
65+
};
66+
67+
QUICHE_EXPORT inline GenericBugOptions DefaultBugOptions(const char* file_name,
68+
int line) {
69+
return GenericBugOptions(absl::kLogDebugFatal, file_name, line);
70+
}
71+
72+
// Called if a GENERIC_BUG is hit, but logging is omitted.
73+
QUICHE_EXPORT void GenericBugWithoutLog(const char* bug_id,
74+
const GenericBugOptions& options);
75+
76+
// GenericBugStreamHandler exposes an interface similar to Abseil log objects,
77+
// and is used by GENERIC_BUG to trigger a function which can be overridden in
78+
// tests. By default, this class performs no action. SetOverrideFunction must be
79+
// called to accomplish anything interesting.
80+
class QUICHE_EXPORT GenericBugStreamHandler {
81+
public:
82+
// |prefix| and |bug_id| must be literal strings. They are used in the
83+
// destructor.
84+
explicit GenericBugStreamHandler(const char* prefix, const char* bug_id,
85+
const GenericBugOptions& options);
86+
87+
~GenericBugStreamHandler();
88+
89+
template <typename T,
90+
std::enable_if_t<absl::HasAbslStringify<T>::value, bool> = true>
91+
QUICHE_EXPORT GenericBugStreamHandler& operator<<(const T& v) {
92+
absl::StrAppend(&str_, v);
93+
return *this;
94+
}
95+
96+
// For types that support only operator<<. There's a better solution in
97+
// Abseil, but unfortunately OStringStream is in a namespace marked internal.
98+
template <typename T,
99+
std::enable_if_t<!absl::HasAbslStringify<T>::value, bool> = true>
100+
QUICHE_EXPORT GenericBugStreamHandler& operator<<(const T& v) {
101+
absl::StrAppend(&str_, (std::ostringstream() << v).view());
102+
return *this;
103+
}
104+
105+
// Interface similar to Abseil log objects.
106+
GenericBugStreamHandler& stream() { return *this; }
107+
108+
using OverrideFunction = void (*)(absl::LogSeverity severity,
109+
const char* file, int line,
110+
absl::string_view log_message);
111+
112+
// Allows overriding the internal implementation. Call with nullptr to make
113+
// this class a no-op. This getter and setter are thread-safe.
114+
static void SetOverrideFunction(OverrideFunction override_function);
115+
static OverrideFunction GetOverrideFunction();
116+
117+
private:
118+
static std::atomic<OverrideFunction> atomic_override_function_;
119+
120+
const char* bug_id_;
121+
std::string str_;
122+
const GenericBugOptions& options_;
123+
};
124+
125+
} // namespace internal
126+
} // namespace quiche
127+
128+
// The GNU compiler emits a warning for code like:
129+
//
130+
// if (foo)
131+
// if (bar) { } else baz;
132+
//
133+
// because it thinks you might want the else to bind to the first if. This
134+
// leads to problems with code like:
135+
//
136+
// if (do_expr) GENERIC_BUG(bug_id) << "Some message";
137+
//
138+
// The "switch (0) case 0:" idiom is used to suppress this.
139+
#define GENERIC_BUG_UNBRACED_ELSE_BLOCKER \
140+
switch (0) \
141+
case 0: \
142+
default:
143+
144+
#define GENERIC_BUG_IMPL(prefix, bug_id, skip_log_condition, options) \
145+
if (skip_log_condition) { \
146+
::quiche::internal::GenericBugWithoutLog(#bug_id, (options)); \
147+
} else /* NOLINT */ \
148+
::quiche::internal::GenericBugStreamHandler(prefix, #bug_id, (options)) \
149+
.stream()
150+
151+
#endif // QUICHE_COMMON_BUG_UTILS_H_

0 commit comments

Comments
 (0)