Index: snapshot/win/exception_snapshot_win_test.cc |
diff --git a/snapshot/win/exception_snapshot_win_test.cc b/snapshot/win/exception_snapshot_win_test.cc |
index 268d64e4a325c0e6f6397525ebec6cf4e430fe70..dbed3f80cfa9777858a62ad111fb0d638b84e3fc 100644 |
--- a/snapshot/win/exception_snapshot_win_test.cc |
+++ b/snapshot/win/exception_snapshot_win_test.cc |
@@ -19,13 +19,13 @@ |
#include "base/strings/stringprintf.h" |
#include "base/strings/utf_string_conversions.h" |
#include "client/crashpad_client.h" |
-#include "client/crashpad_info.h" |
-#include "handler/win/registration_server.h" |
#include "gtest/gtest.h" |
#include "snapshot/win/process_reader_win.h" |
#include "snapshot/win/process_snapshot_win.h" |
#include "test/win/win_child_process.h" |
#include "util/thread/thread.h" |
+#include "util/win/exception_handler_server.h" |
+#include "util/win/registration_protocol_win.h" |
#include "util/win/scoped_handle.h" |
namespace crashpad { |
@@ -48,62 +48,37 @@ HANDLE DuplicateEvent(HANDLE process, HANDLE event) { |
class ExceptionSnapshotWinTest : public testing::Test { |
public: |
- class Delegate : public RegistrationServer::Delegate { |
+ class Delegate : public ExceptionHandlerServer::Delegate { |
public: |
- Delegate() |
- : crashpad_info_address_(0), |
- client_process_(), |
- started_event_(CreateEvent(nullptr, false, false, nullptr)), |
- request_dump_event_(CreateEvent(nullptr, false, false, nullptr)), |
- dump_complete_event_(CreateEvent(nullptr, true, false, nullptr)) { |
- EXPECT_TRUE(started_event_.is_valid()); |
- EXPECT_TRUE(request_dump_event_.is_valid()); |
- EXPECT_TRUE(dump_complete_event_.is_valid()); |
- } |
- |
- ~Delegate() override { |
- } |
- |
- void OnStarted() override { |
- EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(started_event_.get(), 0)); |
- SetEvent(started_event_.get()); |
- } |
+ Delegate(HANDLE server_ready, HANDLE completed_test_event) |
+ : server_ready_(server_ready), |
+ completed_test_event_(completed_test_event), |
+ break_near_(nullptr) {} |
+ ~Delegate() override {} |
- bool RegisterClient(ScopedKernelHANDLE client_process, |
- WinVMAddress crashpad_info_address, |
- HANDLE* request_dump_event, |
- HANDLE* dump_complete_event) override { |
- client_process_ = client_process.Pass(); |
- crashpad_info_address_ = crashpad_info_address; |
- *request_dump_event = |
- DuplicateEvent(client_process_.get(), request_dump_event_.get()); |
- *dump_complete_event = |
- DuplicateEvent(client_process_.get(), dump_complete_event_.get()); |
- return true; |
- } |
- |
- void WaitForStart() { |
- DWORD wait_result = WaitForSingleObject(started_event_.get(), INFINITE); |
- if (wait_result == WAIT_FAILED) |
- PLOG(ERROR); |
- ASSERT_EQ(wait_result, WAIT_OBJECT_0); |
- } |
+ void set_break_near(void* break_near) { break_near_ = break_near; } |
- void WaitForDumpRequestAndValidateException(void* break_near) { |
- // Wait until triggered, and then grab information from the child. |
- WaitForSingleObject(request_dump_event_.get(), INFINITE); |
+ void ExceptionHandlerServerStarted() override { SetEvent(server_ready_); } |
+ unsigned int ExceptionHandlerServerException( |
+ HANDLE process, |
+ WinVMAddress exception_information_address) override { |
// Snapshot the process and exception. |
ProcessReaderWin process_reader; |
- ASSERT_TRUE(process_reader.Initialize(client_process_.get())); |
- CrashpadInfo crashpad_info; |
- ASSERT_TRUE(process_reader.ReadMemory( |
- crashpad_info_address_, sizeof(crashpad_info), &crashpad_info)); |
+ EXPECT_TRUE(process_reader.Initialize(process)); |
+ if (HasFatalFailure()) |
+ return 0xffffffff; |
+ ExceptionInformation exception_information; |
+ EXPECT_TRUE( |
+ process_reader.ReadMemory(exception_information_address, |
+ sizeof(exception_information), |
+ &exception_information)); |
+ if (HasFatalFailure()) |
+ return 0xffffffff; |
ProcessSnapshotWin snapshot; |
- snapshot.Initialize(client_process_.get()); |
- snapshot.InitializeException( |
- crashpad_info.thread_id(), |
- reinterpret_cast<WinVMAddress>(crashpad_info.exception_pointers())); |
+ snapshot.Initialize(process); |
+ snapshot.InitializeException(exception_information.thread_id, |
+ exception_information.exception_pointers); |
// Confirm the exception record was read correctly. |
EXPECT_NE(snapshot.Exception()->ThreadID(), 0u); |
@@ -114,43 +89,42 @@ class ExceptionSnapshotWinTest : public testing::Test { |
// happens. See CrashingChildProcess::Run(). |
const uint64_t kAllowedOffset = 64; |
EXPECT_GT(snapshot.Exception()->ExceptionAddress(), |
- reinterpret_cast<uint64_t>(break_near)); |
+ reinterpret_cast<uint64_t>(break_near_)); |
EXPECT_LT(snapshot.Exception()->ExceptionAddress(), |
- reinterpret_cast<uint64_t>(break_near) + kAllowedOffset); |
+ reinterpret_cast<uint64_t>(break_near_) + kAllowedOffset); |
- // Notify the child that we're done. |
- SetEvent(dump_complete_event_.get()); |
- } |
+ SetEvent(completed_test_event_); |
- ScopedKernelHANDLE* request_dump_event() { return &request_dump_event_; } |
- ScopedKernelHANDLE* dump_complete_event() { return &dump_complete_event_; } |
+ return snapshot.Exception()->Exception(); |
+ } |
private: |
- WinVMAddress crashpad_info_address_; |
- ScopedKernelHANDLE client_process_; |
- ScopedKernelHANDLE started_event_; |
- ScopedKernelHANDLE request_dump_event_; |
- ScopedKernelHANDLE dump_complete_event_; |
+ HANDLE server_ready_; // weak |
+ HANDLE completed_test_event_; // weak |
+ void* break_near_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Delegate); |
}; |
+ |
+ private: |
+ ScopedKernelHANDLE exception_happened_; |
}; |
-// Runs the RegistrationServer on a background thread. |
+// Runs the ExceptionHandlerServer on a background thread. |
class RunServerThread : public Thread { |
public: |
- // Instantiates a thread which will invoke server->Run(pipe_name, delegate). |
- RunServerThread(RegistrationServer* server, |
- const base::string16& pipe_name, |
- RegistrationServer::Delegate* delegate) |
- : server_(server), pipe_name_(pipe_name), delegate_(delegate) {} |
+ // Instantiates a thread which will invoke server->Run(pipe_name); |
+ explicit RunServerThread(ExceptionHandlerServer* server, |
+ const std::string& pipe_name) |
+ : server_(server), pipe_name_(pipe_name) {} |
~RunServerThread() override {} |
private: |
// Thread: |
- void ThreadMain() override { server_->Run(pipe_name_, delegate_); } |
+ void ThreadMain() override { server_->Run(pipe_name_); } |
- RegistrationServer* server_; |
- base::string16 pipe_name_; |
- RegistrationServer::Delegate* delegate_; |
+ ExceptionHandlerServer* server_; |
+ std::string pipe_name_; |
DISALLOW_COPY_AND_ASSIGN(RunServerThread); |
}; |
@@ -159,7 +133,7 @@ class RunServerThread : public Thread { |
// thread joined. |
class ScopedStopServerAndJoinThread { |
public: |
- explicit ScopedStopServerAndJoinThread(RegistrationServer* server, |
+ explicit ScopedStopServerAndJoinThread(ExceptionHandlerServer* server, |
Thread* thread) |
: server_(server), thread_(thread) {} |
~ScopedStopServerAndJoinThread() { |
@@ -168,7 +142,7 @@ class ScopedStopServerAndJoinThread { |
} |
private: |
- RegistrationServer* server_; |
+ ExceptionHandlerServer* server_; |
Thread* thread_; |
DISALLOW_COPY_AND_ASSIGN(ScopedStopServerAndJoinThread); |
}; |
@@ -213,29 +187,36 @@ class CrashingChildProcess final : public WinChildProcess { |
}; |
TEST_F(ExceptionSnapshotWinTest, ChildCrash) { |
+ // Spawn a child process that will immediately crash (once we let it |
+ // run below by telling it what to connect to). |
+ WinChildProcess::EntryPoint<CrashingChildProcess>(); |
+ scoped_ptr<WinChildProcess::Handles> handle = WinChildProcess::Launch(); |
+ |
// Set up the registration server on a background thread. |
- RegistrationServer server; |
std::string pipe_name = "\\\\.\\pipe\\handler_test_pipe_" + |
base::StringPrintf("%08x", GetCurrentProcessId()); |
- base::string16 pipe_name_16 = base::UTF8ToUTF16(pipe_name); |
- Delegate delegate; |
- RunServerThread server_thread(&server, pipe_name_16, &delegate); |
+ ScopedKernelHANDLE server_ready(CreateEvent(nullptr, false, false, nullptr)); |
+ ScopedKernelHANDLE completed(CreateEvent(nullptr, false, false, nullptr)); |
+ Delegate delegate(server_ready.get(), completed.get()); |
+ |
+ ExceptionHandlerServer exception_handler_server(&delegate); |
+ RunServerThread server_thread(&exception_handler_server, pipe_name); |
server_thread.Start(); |
ScopedStopServerAndJoinThread scoped_stop_server_and_join_thread( |
- &server, &server_thread); |
- ASSERT_NO_FATAL_FAILURE(delegate.WaitForStart()); |
+ &exception_handler_server, &server_thread); |
- // Spawn a child process that immediately crashes. |
- WinChildProcess::EntryPoint<CrashingChildProcess>(); |
- scoped_ptr<WinChildProcess::Handles> handle = WinChildProcess::Launch(); |
+ WaitForSingleObject(server_ready.get(), INFINITE); |
+ // Allow the child to continue and tell it where to connect to. |
WriteString(handle->write.get(), pipe_name); |
+ // The child tells us (approximately) where it will crash. |
void* break_near_address; |
LoggingReadFile( |
handle->read.get(), &break_near_address, sizeof(break_near_address)); |
+ delegate.set_break_near(break_near_address); |
- // Verify the exception information is as expected. |
- delegate.WaitForDumpRequestAndValidateException(break_near_address); |
+ // Wait for the child to crash and the exception information to be validated. |
+ WaitForSingleObject(completed.get(), INFINITE); |
} |
} // namespace |