Skip to content

Commit ec99257

Browse files
authored
Merge pull request #80 from supervacuus/meta/update
meta: update 2023-02-07
2 parents e39c0b6 + 3af012a commit ec99257

File tree

56 files changed

+2949
-96
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+2949
-96
lines changed

BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ if (crashpad_is_in_chromium || crashpad_is_in_fuchsia) {
3939
if (crashpad_is_in_fuchsia) {
4040
# TODO(fuchsia:46559): Fix the leaks and remove this.
4141
deps += [ "//build/config/sanitizers:suppress-lsan.DO-NOT-USE-THIS" ]
42+
# TODO(fxbug.dev/108368): Remove this once the underlying issue is addressed.
43+
exclude_toolchain_tags = [ "hwasan" ]
4244
}
4345
if (crashpad_is_android) {
4446
use_raw_android_executable = true

DEPS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
vars = {
1616
'chromium_git': 'https://chromium.googlesource.com',
17-
'gn_version': 'git_revision:2ecd43a10266bd091c98e6dcde507c64f6a0dad3',
17+
'gn_version': 'git_revision:5e19d2fb166fbd4f6f32147fbb2f497091a54ad8',
1818
# ninja CIPD package version.
1919
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
2020
'ninja_version': 'version:[email protected]',

build/crashpad_buildconfig.gni

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ crashpad_is_standalone = crashpad_dependencies == "standalone"
3737
# This is the parent directory that contains the mini_chromium source dir.
3838
# This variable is not used when crashpad_is_in_chromium.
3939
if (crashpad_is_in_fuchsia) {
40-
mini_chromium_source_parent = "//third_party/crashpad/third_party/mini_chromium"
40+
import("//third_party/crashpad/fuchsia_buildconfig.gni")
41+
mini_chromium_source_parent =
42+
fuchsia_crashpad_root + "/third_party/mini_chromium"
4143
} else {
4244
mini_chromium_source_parent = "../third_party/mini_chromium"
4345
}
@@ -49,7 +51,7 @@ _mini_chromium_source_root = "$mini_chromium_source_parent/mini_chromium"
4951
if (crashpad_is_external || crashpad_is_in_dart) {
5052
mini_chromium_import_root = "../../../$_mini_chromium_source_root"
5153
} else if (crashpad_is_in_fuchsia) {
52-
mini_chromium_import_root = "//third_party/mini_chromium"
54+
mini_chromium_import_root = fuchsia_mini_chromium_root
5355
} else {
5456
mini_chromium_import_root = _mini_chromium_source_root
5557
}

build/run_tests.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,10 @@ def _adb_shell(command_args, env={}):
312312
_adb_shell(['rm', '-rf', device_temp_dir])
313313

314314

315-
def _RunOnIOSTarget(binary_dir, test, is_xcuitest=False):
315+
def _RunOnIOSTarget(binary_dir, test, is_xcuitest=False, gtest_filter=None):
316316
"""Runs the given iOS |test| app on iPhone 8 with the default OS version."""
317317

318-
def xctest(binary_dir, test):
318+
def xctest(binary_dir, test, gtest_filter=None):
319319
"""Returns a dict containing the xctestrun data needed to run an
320320
XCTest-based test app."""
321321
test_path = os.path.join(CRASHPAD_DIR, binary_dir)
@@ -332,6 +332,8 @@ def xctest(binary_dir, test):
332332
'XCInjectBundleInto': '__TESTHOST__/' + test,
333333
}
334334
}
335+
if gtest_filter:
336+
module_data['CommandLineArguments'] = ['--gtest_filter='+gtest_filter]
335337
return {test: module_data}
336338

337339
def xcuitest(binary_dir, test):
@@ -368,16 +370,18 @@ def xcuitest(binary_dir, test):
368370

369371
xctestrun_path = f.name
370372
print(xctestrun_path)
373+
command = [
374+
'xcodebuild', 'test-without-building', '-xctestrun', xctestrun_path,
375+
'-destination', 'platform=iOS Simulator,name=iPhone 8',
376+
]
371377
with open(xctestrun_path, 'wb') as fp:
372378
if is_xcuitest:
373379
plistlib.dump(xcuitest(binary_dir, test), fp)
380+
if gtest_filter:
381+
command.append('-only-testing:' + test + '/' + gtest_filter)
374382
else:
375-
plistlib.dump(xctest(binary_dir, test), fp)
376-
377-
subprocess.check_call([
378-
'xcodebuild', 'test-without-building', '-xctestrun', xctestrun_path,
379-
'-destination', 'platform=iOS Simulator,name=iPhone 8'
380-
])
383+
plistlib.dump(xctest(binary_dir, test, gtest_filter), fp)
384+
subprocess.check_call(command)
381385

382386

383387
# This script is primarily used from the waterfall so that the list of tests
@@ -468,7 +472,8 @@ def main(args):
468472
elif is_ios:
469473
_RunOnIOSTarget(args.binary_dir,
470474
test,
471-
is_xcuitest=test.startswith('ios'))
475+
is_xcuitest=test.startswith('ios'),
476+
gtest_filter=args.gtest_filter)
472477
else:
473478
subprocess.check_call([os.path.join(args.binary_dir, test)] +
474479
extra_command_line)

client/BUILD.gn

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ static_library("common") {
119119
"crash_report_database.h",
120120
"crashpad_info.cc",
121121
"crashpad_info.h",
122+
"length_delimited_ring_buffer.h",
123+
"ring_buffer_annotation.h",
122124
"settings.cc",
123125
"settings.h",
124126
"simple_address_range_bag.h",
@@ -147,14 +149,28 @@ static_library("common") {
147149
configs += [ "../build:flock_always_supported_defines" ]
148150
}
149151

152+
crashpad_executable("ring_buffer_annotation_load_test") {
153+
testonly = true
154+
sources = [
155+
"ring_buffer_annotation_load_test_main.cc",
156+
]
157+
deps = [
158+
":client",
159+
"../tools:tool_support",
160+
"$mini_chromium_source_parent:base",
161+
]
162+
}
163+
150164
source_set("client_test") {
151165
testonly = true
152166

153167
sources = [
154168
"annotation_list_test.cc",
155169
"annotation_test.cc",
156170
"crash_report_database_test.cc",
171+
"length_delimited_ring_buffer_test.cc",
157172
"prune_crash_reports_test.cc",
173+
"ring_buffer_annotation_test.cc",
158174
"settings_test.cc",
159175
"simple_address_range_bag_test.cc",
160176
"simple_string_dictionary_test.cc",

client/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ add_library(crashpad_client STATIC
88
crashpad_client.h
99
crashpad_info.cc
1010
crashpad_info.h
11+
length_delimited_ring_buffer.h
12+
ring_buffer_annotation.h
1113
prune_crash_reports.cc
1214
prune_crash_reports.h
1315
settings.cc

client/annotation.h

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <algorithm>
1919
#include <atomic>
20+
#include <optional>
2021

2122
#include <stdint.h>
2223
#include <string.h>
@@ -26,6 +27,7 @@
2627
#include "base/numerics/safe_conversions.h"
2728
#include "base/strings/string_piece.h"
2829
#include "build/build_config.h"
30+
#include "util/synchronization/scoped_spin_guard.h"
2931

3032
namespace crashpad {
3133
#if BUILDFLAG(IS_IOS)
@@ -94,6 +96,20 @@ class Annotation {
9496
kUserDefinedStart = 0x8000,
9597
};
9698

99+
//! \brief Mode used to guard concurrent reads from writes.
100+
enum class ConcurrentAccessGuardMode : bool {
101+
//! \!brief Annotation does not guard reads from concurrent
102+
//! writes. Annotation values can be corrupted if the process crashes
103+
//! mid-write and the handler tries to read from the Annotation while
104+
//! being written to.
105+
kUnguarded = false,
106+
107+
//! \!brief Annotation guards reads from concurrent writes using
108+
//! ScopedSpinGuard. Clients must use TryCreateScopedSpinGuard()
109+
//! before reading or writing the data in this Annotation.
110+
kScopedSpinGuard = true,
111+
};
112+
97113
//! \brief Creates a user-defined Annotation::Type.
98114
//!
99115
//! This exists to remove the casting overhead of `enum class`.
@@ -132,12 +148,11 @@ class Annotation {
132148
//! \param[in] value_ptr A pointer to the value for the annotation. The
133149
//! pointer may not be changed once associated with an annotation, but
134150
//! the data may be mutated.
135-
constexpr Annotation(Type type, const char name[], void* const value_ptr)
136-
: link_node_(nullptr),
137-
name_(name),
138-
value_ptr_(value_ptr),
139-
size_(0),
140-
type_(type) {}
151+
constexpr Annotation(Type type, const char name[], void* value_ptr)
152+
: Annotation(type,
153+
name,
154+
value_ptr,
155+
ConcurrentAccessGuardMode::kUnguarded) {}
141156

142157
Annotation(const Annotation&) = delete;
143158
Annotation& operator=(const Annotation&) = delete;
@@ -172,7 +187,58 @@ class Annotation {
172187
const char* name() const { return name_; }
173188
const void* value() const { return value_ptr_; }
174189

190+
ConcurrentAccessGuardMode concurrent_access_guard_mode() const {
191+
return concurrent_access_guard_mode_;
192+
}
193+
194+
//! \brief If this Annotation guards concurrent access using ScopedSpinGuard,
195+
//! tries to obtain the spin guard and returns the result.
196+
//!
197+
//! \param[in] timeout_ns The timeout in nanoseconds after which to give up
198+
//! trying to obtain the spin guard.
199+
//! \return std::nullopt if the spin guard could not be obtained within
200+
//! timeout_ns, or the obtained spin guard otherwise.
201+
std::optional<ScopedSpinGuard> TryCreateScopedSpinGuard(uint64_t timeout_ns) {
202+
// This can't use DCHECK_EQ() because ostream doesn't support
203+
// operator<<(bool).
204+
DCHECK(concurrent_access_guard_mode_ ==
205+
ConcurrentAccessGuardMode::kScopedSpinGuard);
206+
if (concurrent_access_guard_mode_ ==
207+
ConcurrentAccessGuardMode::kUnguarded) {
208+
return std::nullopt;
209+
}
210+
return ScopedSpinGuard::TryCreateScopedSpinGuard(timeout_ns,
211+
spin_guard_state_);
212+
}
213+
175214
protected:
215+
//! \brief Constructs a new annotation.
216+
//!
217+
//! Upon construction, the annotation will not be included in any crash
218+
//! reports until \sa SetSize() is called with a value greater than `0`.
219+
//!
220+
//! \param[in] type The data type of the value of the annotation.
221+
//! \param[in] name A `NUL`-terminated C-string name for the annotation. Names
222+
//! do not have to be unique, though not all crash processors may handle
223+
//! Annotations with the same name. Names should be constexpr data with
224+
//! static storage duration.
225+
//! \param[in] value_ptr A pointer to the value for the annotation. The
226+
//! pointer may not be changed once associated with an annotation, but
227+
//! the data may be mutated.
228+
//! \param[in] concurrent_access_guard_mode Mode used to guard concurrent
229+
//! reads from writes.
230+
constexpr Annotation(Type type,
231+
const char name[],
232+
void* value_ptr,
233+
ConcurrentAccessGuardMode concurrent_access_guard_mode)
234+
: link_node_(nullptr),
235+
name_(name),
236+
value_ptr_(value_ptr),
237+
size_(0),
238+
type_(type),
239+
concurrent_access_guard_mode_(concurrent_access_guard_mode),
240+
spin_guard_state_() {}
241+
176242
friend class AnnotationList;
177243
#if BUILDFLAG(IS_IOS)
178244
friend class internal::InProcessIntermediateDumpHandler;
@@ -192,6 +258,11 @@ class Annotation {
192258
void* const value_ptr_;
193259
ValueSizeType size_;
194260
const Type type_;
261+
262+
//! \brief Mode used to guard concurrent reads from writes.
263+
const ConcurrentAccessGuardMode concurrent_access_guard_mode_;
264+
265+
SpinGuardState spin_guard_state_;
195266
};
196267

197268
//! \brief An \sa Annotation that stores a `NUL`-terminated C-string value.

client/annotation_test.cc

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,58 @@
2121
#include "client/crashpad_info.h"
2222
#include "gtest/gtest.h"
2323
#include "test/gtest_death.h"
24+
#include "util/misc/clock.h"
25+
#include "util/synchronization/scoped_spin_guard.h"
26+
#include "util/thread/thread.h"
2427

2528
namespace crashpad {
2629
namespace test {
2730
namespace {
2831

32+
class SpinGuardAnnotation final : public Annotation {
33+
public:
34+
SpinGuardAnnotation(Annotation::Type type, const char name[])
35+
: Annotation(type,
36+
name,
37+
&value_,
38+
ConcurrentAccessGuardMode::kScopedSpinGuard) {}
39+
40+
bool Set(bool value, uint64_t spin_guard_timeout_ns) {
41+
auto guard = TryCreateScopedSpinGuard(spin_guard_timeout_ns);
42+
if (!guard) {
43+
return false;
44+
}
45+
value_ = value;
46+
SetSize(sizeof(value_));
47+
return true;
48+
}
49+
50+
private:
51+
bool value_;
52+
};
53+
54+
class ScopedSpinGuardUnlockThread final : public Thread {
55+
public:
56+
ScopedSpinGuardUnlockThread(ScopedSpinGuard scoped_spin_guard,
57+
uint64_t sleep_time_ns)
58+
: scoped_spin_guard_(std::move(scoped_spin_guard)),
59+
sleep_time_ns_(sleep_time_ns) {}
60+
61+
private:
62+
void ThreadMain() override {
63+
SleepNanoseconds(sleep_time_ns_);
64+
65+
// Move the ScopedSpinGuard member into a local variable which is
66+
// destroyed when ThreadMain() returns.
67+
ScopedSpinGuard local_scoped_spin_guard(std::move(scoped_spin_guard_));
68+
69+
// After this point, local_scoped_spin_guard will be destroyed and unlocked.
70+
}
71+
72+
ScopedSpinGuard scoped_spin_guard_;
73+
const uint64_t sleep_time_ns_;
74+
};
75+
2976
class Annotation : public testing::Test {
3077
public:
3178
void SetUp() override {
@@ -108,6 +155,61 @@ TEST_F(Annotation, StringType) {
108155
EXPECT_EQ("loooo", annotation.value());
109156
}
110157

158+
TEST_F(Annotation, BaseAnnotationShouldNotSupportSpinGuard) {
159+
char buffer[1024];
160+
crashpad::Annotation annotation(
161+
crashpad::Annotation::Type::kString, "no-spin-guard", buffer);
162+
EXPECT_EQ(annotation.concurrent_access_guard_mode(),
163+
crashpad::Annotation::ConcurrentAccessGuardMode::kUnguarded);
164+
#ifdef NDEBUG
165+
// This fails a DCHECK() in debug builds, so only test it for NDEBUG builds.
166+
EXPECT_EQ(std::nullopt, annotation.TryCreateScopedSpinGuard(0));
167+
#endif
168+
}
169+
170+
TEST_F(Annotation, CustomAnnotationShouldSupportSpinGuardAndSet) {
171+
constexpr crashpad::Annotation::Type kType =
172+
crashpad::Annotation::UserDefinedType(1);
173+
SpinGuardAnnotation spin_guard_annotation(kType, "spin-guard");
174+
EXPECT_EQ(spin_guard_annotation.concurrent_access_guard_mode(),
175+
crashpad::Annotation::ConcurrentAccessGuardMode::kScopedSpinGuard);
176+
EXPECT_TRUE(spin_guard_annotation.Set(true, 0));
177+
EXPECT_EQ(1U, spin_guard_annotation.size());
178+
}
179+
180+
TEST_F(Annotation, CustomAnnotationSetShouldFailIfRunConcurrently) {
181+
constexpr crashpad::Annotation::Type kType =
182+
crashpad::Annotation::UserDefinedType(1);
183+
SpinGuardAnnotation spin_guard_annotation(kType, "spin-guard");
184+
auto guard = spin_guard_annotation.TryCreateScopedSpinGuard(0);
185+
EXPECT_NE(std::nullopt, guard);
186+
// This should fail, since the guard is already held and the timeout is 0.
187+
EXPECT_FALSE(spin_guard_annotation.Set(true, 0));
188+
}
189+
190+
TEST_F(Annotation,
191+
CustomAnnotationSetShouldSucceedIfSpinGuardUnlockedAsynchronously) {
192+
constexpr crashpad::Annotation::Type kType =
193+
crashpad::Annotation::UserDefinedType(1);
194+
SpinGuardAnnotation spin_guard_annotation(kType, "spin-guard");
195+
auto guard = spin_guard_annotation.TryCreateScopedSpinGuard(0);
196+
EXPECT_NE(std::nullopt, guard);
197+
// Pass the guard off to a background thread which unlocks it after 1 ms.
198+
constexpr uint64_t kSleepTimeNs = 1000000; // 1 ms
199+
ScopedSpinGuardUnlockThread unlock_thread(std::move(guard.value()),
200+
kSleepTimeNs);
201+
unlock_thread.Start();
202+
203+
// Try to set the annotation with a 100 ms timeout.
204+
constexpr uint64_t kSpinGuardTimeoutNanos = 100000000; // 100 ms
205+
206+
// This should succeed after 1 ms, since the timeout is much larger than the
207+
// time the background thread holds the guard.
208+
EXPECT_TRUE(spin_guard_annotation.Set(true, kSpinGuardTimeoutNanos));
209+
210+
unlock_thread.Join();
211+
}
212+
111213
TEST(StringAnnotation, ArrayOfString) {
112214
static crashpad::StringAnnotation<4> annotations[] = {
113215
{"test-1", crashpad::StringAnnotation<4>::Tag::kArray},

0 commit comments

Comments
 (0)