Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(638)

Side by Side Diff: snapshot/win/exception_snapshot_win_test.cc

Issue 1356383002: win: Implement CRASHPAD_SIMULATE_CRASH() (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: fixes Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Crashpad Authors. All rights reserved. 1 // Copyright 2015 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 18 matching lines...) Expand all
29 #include "util/thread/thread.h" 29 #include "util/thread/thread.h"
30 #include "util/win/exception_handler_server.h" 30 #include "util/win/exception_handler_server.h"
31 #include "util/win/registration_protocol_win.h" 31 #include "util/win/registration_protocol_win.h"
32 #include "util/win/scoped_handle.h" 32 #include "util/win/scoped_handle.h"
33 #include "util/win/scoped_process_suspend.h" 33 #include "util/win/scoped_process_suspend.h"
34 34
35 namespace crashpad { 35 namespace crashpad {
36 namespace test { 36 namespace test {
37 namespace { 37 namespace {
38 38
39 HANDLE DuplicateEvent(HANDLE process, HANDLE event) { 39 // Runs the ExceptionHandlerServer on a background thread.
40 HANDLE handle; 40 class RunServerThread : public Thread {
41 if (DuplicateHandle(GetCurrentProcess(), 41 public:
42 event, 42 // Instantiates a thread which will invoke server->Run(delegate, pipe_name);
43 process, 43 RunServerThread(ExceptionHandlerServer* server,
44 &handle, 44 ExceptionHandlerServer::Delegate* delegate,
45 SYNCHRONIZE | EVENT_MODIFY_STATE, 45 const std::string& pipe_name)
46 false, 46 : server_(server), delegate_(delegate), pipe_name_(pipe_name) {}
47 0)) { 47 ~RunServerThread() override {}
48 return handle; 48
49 private:
50 // Thread:
51 void ThreadMain() override { server_->Run(delegate_, pipe_name_); }
52
53 ExceptionHandlerServer* server_;
54 ExceptionHandlerServer::Delegate* delegate_;
55 std::string pipe_name_;
56
57 DISALLOW_COPY_AND_ASSIGN(RunServerThread);
58 };
59
60 // During destruction, ensures that the server is stopped and the background
61 // thread joined.
62 class ScopedStopServerAndJoinThread {
63 public:
64 ScopedStopServerAndJoinThread(ExceptionHandlerServer* server, Thread* thread)
65 : server_(server), thread_(thread) {}
66 ~ScopedStopServerAndJoinThread() {
67 server_->Stop();
68 thread_->Join();
49 } 69 }
50 return nullptr;
51 }
52 70
53 class Delegate : public ExceptionHandlerServer::Delegate { 71 private:
72 ExceptionHandlerServer* server_;
73 Thread* thread_;
74 DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread);
75 };
76
77 class CrashingDelegate : public ExceptionHandlerServer::Delegate {
54 public: 78 public:
55 Delegate(HANDLE server_ready, HANDLE completed_test_event) 79 CrashingDelegate(HANDLE server_ready, HANDLE completed_test_event)
56 : server_ready_(server_ready), 80 : server_ready_(server_ready),
57 completed_test_event_(completed_test_event), 81 completed_test_event_(completed_test_event),
58 break_near_(0) {} 82 break_near_(0) {}
59 ~Delegate() override {} 83 ~CrashingDelegate() override {}
60 84
61 void set_break_near(WinVMAddress break_near) { break_near_ = break_near; } 85 void set_break_near(WinVMAddress break_near) { break_near_ = break_near; }
62 86
63 void ExceptionHandlerServerStarted() override { SetEvent(server_ready_); } 87 void ExceptionHandlerServerStarted() override { SetEvent(server_ready_); }
64 88
65 unsigned int ExceptionHandlerServerException( 89 unsigned int ExceptionHandlerServerException(
66 HANDLE process, 90 HANDLE process,
67 WinVMAddress exception_information_address) override { 91 WinVMAddress exception_information_address) override {
68 ScopedProcessSuspend suspend(process); 92 ScopedProcessSuspend suspend(process);
69 ProcessSnapshotWin snapshot; 93 ProcessSnapshotWin snapshot;
70 snapshot.Initialize(process, ProcessSuspensionState::kSuspended); 94 snapshot.Initialize(process, ProcessSuspensionState::kSuspended);
71 snapshot.InitializeException(exception_information_address); 95 snapshot.InitializeException(exception_information_address);
72 96
73 // Confirm the exception record was read correctly. 97 // Confirm the exception record was read correctly.
74 EXPECT_NE(snapshot.Exception()->ThreadID(), 0u); 98 EXPECT_NE(snapshot.Exception()->ThreadID(), 0u);
75 EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT); 99 EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT);
76 100
77 // Verify the exception happened at the expected location with a bit of 101 // Verify the exception happened at the expected location with a bit of
78 // slop space to allow for reading the current PC before the exception 102 // slop space to allow for reading the current PC before the exception
79 // happens. See CrashingChildProcess::Run(). 103 // happens. See TestCrashingChild().
80 const uint64_t kAllowedOffset = 64; 104 const uint64_t kAllowedOffset = 64;
81 EXPECT_GT(snapshot.Exception()->ExceptionAddress(), break_near_); 105 EXPECT_GT(snapshot.Exception()->ExceptionAddress(), break_near_);
82 EXPECT_LT(snapshot.Exception()->ExceptionAddress(), 106 EXPECT_LT(snapshot.Exception()->ExceptionAddress(),
83 break_near_ + kAllowedOffset); 107 break_near_ + kAllowedOffset);
84 108
85 SetEvent(completed_test_event_); 109 SetEvent(completed_test_event_);
86 110
87 return snapshot.Exception()->Exception(); 111 return snapshot.Exception()->Exception();
88 } 112 }
89 113
90 private: 114 private:
91 HANDLE server_ready_; // weak 115 HANDLE server_ready_; // weak
92 HANDLE completed_test_event_; // weak 116 HANDLE completed_test_event_; // weak
93 WinVMAddress break_near_; 117 WinVMAddress break_near_;
94 118
95 DISALLOW_COPY_AND_ASSIGN(Delegate); 119 DISALLOW_COPY_AND_ASSIGN(CrashingDelegate);
96 };
97
98 // Runs the ExceptionHandlerServer on a background thread.
99 class RunServerThread : public Thread {
100 public:
101 // Instantiates a thread which will invoke server->Run(delegate, pipe_name);
102 RunServerThread(ExceptionHandlerServer* server,
103 ExceptionHandlerServer::Delegate* delegate,
104 const std::string& pipe_name)
105 : server_(server), delegate_(delegate), pipe_name_(pipe_name) {}
106 ~RunServerThread() override {}
107
108 private:
109 // Thread:
110 void ThreadMain() override { server_->Run(delegate_, pipe_name_); }
111
112 ExceptionHandlerServer* server_;
113 ExceptionHandlerServer::Delegate* delegate_;
114 std::string pipe_name_;
115
116 DISALLOW_COPY_AND_ASSIGN(RunServerThread);
117 };
118
119 // During destruction, ensures that the server is stopped and the background
120 // thread joined.
121 class ScopedStopServerAndJoinThread {
122 public:
123 ScopedStopServerAndJoinThread(ExceptionHandlerServer* server, Thread* thread)
124 : server_(server), thread_(thread) {}
125 ~ScopedStopServerAndJoinThread() {
126 server_->Stop();
127 thread_->Join();
128 }
129
130 private:
131 ExceptionHandlerServer* server_;
132 Thread* thread_;
133 DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread);
134 }; 120 };
135 121
136 void TestCrashingChild(const base::string16& directory_modification) { 122 void TestCrashingChild(const base::string16& directory_modification) {
137 // Set up the registration server on a background thread. 123 // Set up the registration server on a background thread.
138 std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" + 124 std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" +
139 base::StringPrintf("%08x", GetCurrentProcessId()); 125 base::StringPrintf("%08x", GetCurrentProcessId());
140 ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr)); 126 ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
141 ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr)); 127 ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr));
142 Delegate delegate(server_ready.get(), completed.get()); 128 CrashingDelegate delegate(server_ready.get(), completed.get());
143 129
144 ExceptionHandlerServer exception_handler_server; 130 ExceptionHandlerServer exception_handler_server;
145 RunServerThread server_thread( 131 RunServerThread server_thread(
146 &exception_handler_server, &delegate, pipe_name); 132 &exception_handler_server, &delegate, pipe_name);
147 server_thread.Start(); 133 server_thread.Start();
148 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( 134 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
149 &exception_handler_server, &server_thread); 135 &exception_handler_server, &server_thread);
150 136
151 WaitForSingleObject(server_ready.get(), INFINITE); 137 WaitForSingleObject(server_ready.get(), INFINITE);
152 138
(...skipping 26 matching lines...) Expand all
179 #if defined(ARCH_CPU_64_BITS) 165 #if defined(ARCH_CPU_64_BITS)
180 TEST(ExceptionSnapshotWinTest, ChildCrashWOW64) { 166 TEST(ExceptionSnapshotWinTest, ChildCrashWOW64) {
181 #ifndef NDEBUG 167 #ifndef NDEBUG
182 TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Debug")); 168 TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
183 #else 169 #else
184 TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Release")); 170 TestCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Release"));
185 #endif 171 #endif
186 } 172 }
187 #endif // ARCH_CPU_64_BITS 173 #endif // ARCH_CPU_64_BITS
188 174
175 class SimulateDelegate : public ExceptionHandlerServer::Delegate {
176 public:
177 SimulateDelegate(HANDLE server_ready, HANDLE completed_test_event)
178 : server_ready_(server_ready),
179 completed_test_event_(completed_test_event),
180 dump_near_(0) {}
181 ~SimulateDelegate() override {}
182
183 void set_dump_near(WinVMAddress dump_near) { dump_near_ = dump_near; }
184
185 void ExceptionHandlerServerStarted() override { SetEvent(server_ready_); }
186
187 unsigned int ExceptionHandlerServerException(
188 HANDLE process,
189 WinVMAddress exception_information_address) override {
190 ScopedProcessSuspend suspend(process);
191 ProcessSnapshotWin snapshot;
192 snapshot.Initialize(process, ProcessSuspensionState::kSuspended);
193 snapshot.InitializeException(exception_information_address);
194 EXPECT_TRUE(snapshot.Exception());
195 EXPECT_EQ(0, snapshot.Exception()->Exception());
196 EXPECT_EQ(0, snapshot.Exception()->ExceptionAddress());
197
198 // Verify the dump was captured at the expected location with some slop
199 // space.
200 const uint64_t kAllowedOffset = 64;
201 EXPECT_GT(snapshot.Exception()->Context()->InstructionPointer(),
202 dump_near_);
203 EXPECT_LT(snapshot.Exception()->Context()->InstructionPointer(),
204 dump_near_ + kAllowedOffset);
205
206 SetEvent(completed_test_event_);
207
208 return 0;
209 }
210
211 private:
212 HANDLE server_ready_; // weak
213 HANDLE completed_test_event_; // weak
214 WinVMAddress dump_near_;
215
216 DISALLOW_COPY_AND_ASSIGN(SimulateDelegate);
217 };
218
219 void TestDumpWithoutCrashingChild(
220 const base::string16& directory_modification) {
221 // Set up the registration server on a background thread.
222 std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" +
223 base::StringPrintf("%08x", GetCurrentProcessId());
224 ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
225 ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr));
226 SimulateDelegate delegate(server_ready.get(), completed.get());
227
228 ExceptionHandlerServer exception_handler_server;
229 RunServerThread server_thread(
230 &exception_handler_server, &delegate, pipe_name);
231 server_thread.Start();
232 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
233 &exception_handler_server, &server_thread);
234
235 WaitForSingleObject(server_ready.get(), INFINITE);
236
237 // Spawn a child process, passing it the pipe name to connect to.
238 base::FilePath test_executable = Paths::Executable();
239 std::wstring child_test_executable =
240 test_executable.DirName()
241 .Append(directory_modification)
242 .Append(test_executable.BaseName().RemoveFinalExtension().value() +
243 L"_dump_without_crashing.exe")
244 .value();
245 ChildLauncher child(child_test_executable, base::UTF8ToUTF16(pipe_name));
246 child.Start();
247
248 // The child tells us (approximately) where it will capture a dump.
249 WinVMAddress dump_near_address;
250 LoggingReadFile(child.stdout_read_handle(),
251 &dump_near_address,
252 sizeof(dump_near_address));
253 delegate.set_dump_near(dump_near_address);
254
255 // Wait for the child to crash and the exception information to be validated.
256 WaitForSingleObject(completed.get(), INFINITE);
257 }
258
259 TEST(SimulateCrash, ChildDumpWithoutCrashing) {
260 TestDumpWithoutCrashingChild(FILE_PATH_LITERAL("."));
261 }
262
263 #if defined(ARCH_CPU_64_BITS)
264 TEST(SimulateCrash, ChildDumpWithoutCrashingWOW64) {
265 #ifndef NDEBUG
266 TestDumpWithoutCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Debug"));
267 #else
268 TestDumpWithoutCrashingChild(FILE_PATH_LITERAL("..\\..\\out\\Release"));
269 #endif
270 }
271 #endif // ARCH_CPU_64_BITS
272
189 } // namespace 273 } // namespace
190 } // namespace test 274 } // namespace test
191 } // namespace crashpad 275 } // namespace crashpad
OLDNEW
« no previous file with comments | « snapshot/win/crashpad_snapshot_test_dump_without_crashing.cc ('k') | util/win/exception_handler_server.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698