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

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

Issue 1301853002: win: Crash handler server (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: fixes and move some things around Created 5 years, 3 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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "snapshot/win/exception_snapshot_win.h" 15 #include "snapshot/win/exception_snapshot_win.h"
16 16
17 #include <string> 17 #include <string>
18 18
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
21 #include "client/crashpad_client.h" 21 #include "client/crashpad_client.h"
22 #include "client/crashpad_info.h"
23 #include "handler/win/registration_server.h"
24 #include "gtest/gtest.h" 22 #include "gtest/gtest.h"
25 #include "snapshot/win/process_reader_win.h" 23 #include "snapshot/win/process_reader_win.h"
26 #include "snapshot/win/process_snapshot_win.h" 24 #include "snapshot/win/process_snapshot_win.h"
27 #include "test/win/win_child_process.h" 25 #include "test/win/win_child_process.h"
28 #include "util/thread/thread.h" 26 #include "util/thread/thread.h"
27 #include "util/win/exception_handler_server.h"
28 #include "util/win/registration_protocol_win.h"
29 #include "util/win/scoped_handle.h" 29 #include "util/win/scoped_handle.h"
30 30
31 namespace crashpad { 31 namespace crashpad {
32 namespace test { 32 namespace test {
33 namespace { 33 namespace {
34 34
35 HANDLE DuplicateEvent(HANDLE process, HANDLE event) { 35 HANDLE DuplicateEvent(HANDLE process, HANDLE event) {
36 HANDLE handle; 36 HANDLE handle;
37 if (DuplicateHandle(GetCurrentProcess(), 37 if (DuplicateHandle(GetCurrentProcess(),
38 event, 38 event,
39 process, 39 process,
40 &handle, 40 &handle,
41 SYNCHRONIZE | EVENT_MODIFY_STATE, 41 SYNCHRONIZE | EVENT_MODIFY_STATE,
42 false, 42 false,
43 0)) { 43 0)) {
44 return handle; 44 return handle;
45 } 45 }
46 return nullptr; 46 return nullptr;
47 } 47 }
48 48
49 class ExceptionSnapshotWinTest : public testing::Test { 49 class ExceptionSnapshotWinTest : public testing::Test {
50 public: 50 public:
51 class Delegate : public RegistrationServer::Delegate { 51 class Delegate : public ExceptionHandlerServer::Delegate {
52 public: 52 public:
53 Delegate() 53 Delegate(HANDLE server_ready, HANDLE completed_test_event)
54 : crashpad_info_address_(0), 54 : server_ready_(server_ready),
55 client_process_(), 55 completed_test_event_(completed_test_event),
56 started_event_(CreateEvent(nullptr, false, false, nullptr)), 56 break_near_(nullptr) {}
57 request_dump_event_(CreateEvent(nullptr, false, false, nullptr)), 57 ~Delegate() override {}
58 dump_complete_event_(CreateEvent(nullptr, true, false, nullptr)) { 58
59 EXPECT_TRUE(started_event_.is_valid()); 59 void set_break_near(void* break_near) { break_near_ = break_near; }
60 EXPECT_TRUE(request_dump_event_.is_valid()); 60
61 EXPECT_TRUE(dump_complete_event_.is_valid()); 61 void OnStarted() override {
62 SetEvent(server_ready_);
62 } 63 }
63 64
64 ~Delegate() override { 65 void OnException(HANDLE process,
65 } 66 WinVMAddress exception_information_address) override {
66
67 void OnStarted() override {
68 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(started_event_.get(), 0));
69 SetEvent(started_event_.get());
70 }
71
72 bool RegisterClient(ScopedKernelHANDLE client_process,
73 WinVMAddress crashpad_info_address,
74 HANDLE* request_dump_event,
75 HANDLE* dump_complete_event) override {
76 client_process_ = client_process.Pass();
77 crashpad_info_address_ = crashpad_info_address;
78 *request_dump_event =
79 DuplicateEvent(client_process_.get(), request_dump_event_.get());
80 *dump_complete_event =
81 DuplicateEvent(client_process_.get(), dump_complete_event_.get());
82 return true;
83 }
84
85 void WaitForStart() {
86 DWORD wait_result = WaitForSingleObject(started_event_.get(), INFINITE);
87 if (wait_result == WAIT_FAILED)
88 PLOG(ERROR);
89 ASSERT_EQ(wait_result, WAIT_OBJECT_0);
90 }
91
92 void WaitForDumpRequestAndValidateException(void* break_near) {
93 // Wait until triggered, and then grab information from the child.
94 WaitForSingleObject(request_dump_event_.get(), INFINITE);
95
96 // Snapshot the process and exception. 67 // Snapshot the process and exception.
97 ProcessReaderWin process_reader; 68 ProcessReaderWin process_reader;
98 ASSERT_TRUE(process_reader.Initialize(client_process_.get())); 69 ASSERT_TRUE(process_reader.Initialize(process));
99 CrashpadInfo crashpad_info; 70 ExceptionInformation exception_information;
100 ASSERT_TRUE(process_reader.ReadMemory( 71 ASSERT_TRUE(
101 crashpad_info_address_, sizeof(crashpad_info), &crashpad_info)); 72 process_reader.ReadMemory(exception_information_address,
73 sizeof(exception_information),
74 &exception_information));
102 ProcessSnapshotWin snapshot; 75 ProcessSnapshotWin snapshot;
103 snapshot.Initialize(client_process_.get()); 76 snapshot.Initialize(process);
104 snapshot.InitializeException( 77 snapshot.InitializeException(exception_information.thread_id,
105 crashpad_info.thread_id(), 78 exception_information.exception_pointers);
106 reinterpret_cast<WinVMAddress>(crashpad_info.exception_pointers()));
107 79
108 // Confirm the exception record was read correctly. 80 // Confirm the exception record was read correctly.
109 EXPECT_NE(snapshot.Exception()->ThreadID(), 0u); 81 EXPECT_NE(snapshot.Exception()->ThreadID(), 0u);
110 EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT); 82 EXPECT_EQ(snapshot.Exception()->Exception(), EXCEPTION_BREAKPOINT);
111 83
112 // Verify the exception happened at the expected location with a bit of 84 // Verify the exception happened at the expected location with a bit of
113 // slop space to allow for reading the current PC before the exception 85 // slop space to allow for reading the current PC before the exception
114 // happens. See CrashingChildProcess::Run(). 86 // happens. See CrashingChildProcess::Run().
115 const uint64_t kAllowedOffset = 64; 87 const uint64_t kAllowedOffset = 64;
116 EXPECT_GT(snapshot.Exception()->ExceptionAddress(), 88 EXPECT_GT(snapshot.Exception()->ExceptionAddress(),
117 reinterpret_cast<uint64_t>(break_near)); 89 reinterpret_cast<uint64_t>(break_near_));
118 EXPECT_LT(snapshot.Exception()->ExceptionAddress(), 90 EXPECT_LT(snapshot.Exception()->ExceptionAddress(),
119 reinterpret_cast<uint64_t>(break_near) + kAllowedOffset); 91 reinterpret_cast<uint64_t>(break_near_) + kAllowedOffset);
120 92
121 // Notify the child that we're done. 93 SetEvent(completed_test_event_);
122 SetEvent(dump_complete_event_.get());
123 } 94 }
124 95
125 ScopedKernelHANDLE* request_dump_event() { return &request_dump_event_; } 96 void OnShutdown() override {}
126 ScopedKernelHANDLE* dump_complete_event() { return &dump_complete_event_; }
127 97
128 private: 98 private:
129 WinVMAddress crashpad_info_address_; 99 HANDLE server_ready_; // weak
130 ScopedKernelHANDLE client_process_; 100 HANDLE completed_test_event_; // weak
131 ScopedKernelHANDLE started_event_; 101 void* break_near_;
132 ScopedKernelHANDLE request_dump_event_; 102
133 ScopedKernelHANDLE dump_complete_event_; 103 DISALLOW_COPY_AND_ASSIGN(Delegate);
134 }; 104 };
105
106 private:
107 ScopedKernelHANDLE exception_happened_;
135 }; 108 };
136 109
137 // Runs the RegistrationServer on a background thread. 110 // Runs the ExceptionHandlerServer on a background thread.
138 class RunServerThread : public Thread { 111 class RunServerThread : public Thread {
139 public: 112 public:
140 // Instantiates a thread which will invoke server->Run(pipe_name, delegate). 113 // Instantiates a thread which will invoke server->Run(pipe_name);
141 RunServerThread(RegistrationServer* server, 114 explicit RunServerThread(ExceptionHandlerServer* server,
142 const base::string16& pipe_name, 115 const std::string& pipe_name)
143 RegistrationServer::Delegate* delegate) 116 : server_(server), pipe_name_(pipe_name) {}
144 : server_(server), pipe_name_(pipe_name), delegate_(delegate) {}
145 ~RunServerThread() override {} 117 ~RunServerThread() override {}
146 118
147 private: 119 private:
148 // Thread: 120 // Thread:
149 void ThreadMain() override { server_->Run(pipe_name_, delegate_); } 121 void ThreadMain() override { server_->Run(pipe_name_); }
150 122
151 RegistrationServer* server_; 123 ExceptionHandlerServer* server_;
152 base::string16 pipe_name_; 124 std::string pipe_name_;
153 RegistrationServer::Delegate* delegate_;
154 125
155 DISALLOW_COPY_AND_ASSIGN(RunServerThread); 126 DISALLOW_COPY_AND_ASSIGN(RunServerThread);
156 }; 127 };
157 128
158 // During destruction, ensures that the server is stopped and the background 129 // During destruction, ensures that the server is stopped and the background
159 // thread joined. 130 // thread joined.
160 class ScopedStopServerAndJoinThread { 131 class ScopedStopServerAndJoinThread {
161 public: 132 public:
162 explicit ScopedStopServerAndJoinThread(RegistrationServer* server, 133 explicit ScopedStopServerAndJoinThread(ExceptionHandlerServer* server,
163 Thread* thread) 134 Thread* thread)
164 : server_(server), thread_(thread) {} 135 : server_(server), thread_(thread) {}
165 ~ScopedStopServerAndJoinThread() { 136 ~ScopedStopServerAndJoinThread() {
166 server_->Stop(); 137 server_->Stop();
167 thread_->Join(); 138 thread_->Join();
168 } 139 }
169 140
170 private: 141 private:
171 RegistrationServer* server_; 142 ExceptionHandlerServer* server_;
172 Thread* thread_; 143 Thread* thread_;
173 DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread); 144 DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread);
174 }; 145 };
175 146
176 std::string ReadString(FileHandle handle) { 147 std::string ReadString(FileHandle handle) {
177 size_t length = 0; 148 size_t length = 0;
178 EXPECT_TRUE(LoggingReadFile(handle, &length, sizeof(length))); 149 EXPECT_TRUE(LoggingReadFile(handle, &length, sizeof(length)));
179 scoped_ptr<char[]> buffer(new char[length]); 150 scoped_ptr<char[]> buffer(new char[length]);
180 EXPECT_TRUE(LoggingReadFile(handle, &buffer[0], length)); 151 EXPECT_TRUE(LoggingReadFile(handle, &buffer[0], length));
181 return std::string(&buffer[0], length); 152 return std::string(&buffer[0], length);
(...skipping 24 matching lines...) Expand all
206 // verify it's in approximately the right location (with a bit of fudge for 177 // verify it's in approximately the right location (with a bit of fudge for
207 // the code between here and the __debugbreak()). 178 // the code between here and the __debugbreak()).
208 void* break_address = CurrentAddress(); 179 void* break_address = CurrentAddress();
209 LoggingWriteFile(WritePipeHandle(), &break_address, sizeof(break_address)); 180 LoggingWriteFile(WritePipeHandle(), &break_address, sizeof(break_address));
210 __debugbreak(); 181 __debugbreak();
211 return 0; 182 return 0;
212 }; 183 };
213 }; 184 };
214 185
215 TEST_F(ExceptionSnapshotWinTest, ChildCrash) { 186 TEST_F(ExceptionSnapshotWinTest, ChildCrash) {
187 // Spawn a child process that will immediately crash (once we let it
188 // run below by telling it what to connect to).
189 WinChildProcess::EntryPoint<CrashingChildProcess>();
190 scoped_ptr<WinChildProcess::Handles> handle = WinChildProcess::Launch();
191
216 // Set up the registration server on a background thread. 192 // Set up the registration server on a background thread.
217 RegistrationServer server;
218 std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" + 193 std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" +
219 base::StringPrintf("%08x", GetCurrentProcessId()); 194 base::StringPrintf("%08x", GetCurrentProcessId());
220 base::string16 pipe_name_16 = base::UTF8ToUTF16(pipe_name); 195 ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr));
221 Delegate delegate; 196 ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr));
222 RunServerThread server_thread(&server, pipe_name_16, &delegate); 197 Delegate delegate(server_ready.get(), completed.get());
198
199 ExceptionHandlerServer exception_handler_server(&delegate);
200 RunServerThread server_thread(&exception_handler_server, pipe_name);
223 server_thread.Start(); 201 server_thread.Start();
224 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( 202 ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread(
225 &server, &server_thread); 203 &exception_handler_server, &server_thread);
226 ASSERT_NO_FATAL_FAILURE(delegate.WaitForStart());
227 204
228 // Spawn a child process that immediately crashes. 205 WaitForSingleObject(server_ready.get(), INFINITE);
229 WinChildProcess::EntryPoint<CrashingChildProcess>(); 206 // Allow the child to continue and tell it where to connect to.
230 scoped_ptr<WinChildProcess::Handles> handle = WinChildProcess::Launch();
231 WriteString(handle->write.get(), pipe_name); 207 WriteString(handle->write.get(), pipe_name);
232 208
209 // The child tells us (approximately) where it will crash.
233 void* break_near_address; 210 void* break_near_address;
234 LoggingReadFile( 211 LoggingReadFile(
235 handle->read.get(), &break_near_address, sizeof(break_near_address)); 212 handle->read.get(), &break_near_address, sizeof(break_near_address));
213 delegate.set_break_near(break_near_address);
236 214
237 // Verify the exception information is as expected. 215 // Wait for the child to crash and the exception information to be validated.
238 delegate.WaitForDumpRequestAndValidateException(break_near_address); 216 WaitForSingleObject(completed.get(), INFINITE);
239 } 217 }
240 218
241 } // namespace 219 } // namespace
242 } // namespace test 220 } // namespace test
243 } // namespace crashpad 221 } // namespace crashpad
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698