Index: chrome/common/nacl_debug_exception_handler_win.cc |
diff --git a/chrome/common/nacl_debug_exception_handler_win.cc b/chrome/common/nacl_debug_exception_handler_win.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5a37955370a1c33310871f2df30f348ddb675524 |
--- /dev/null |
+++ b/chrome/common/nacl_debug_exception_handler_win.cc |
@@ -0,0 +1,82 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/common/nacl_debug_exception_handler_win.h" |
+ |
+#include "base/process_util.h" |
+#include "base/threading/platform_thread.h" |
+#include "native_client/src/trusted/service_runtime/win/debug_exception_handler.h" |
+ |
+namespace { |
+ |
+class DebugExceptionHandler : public base::PlatformThread::Delegate { |
+ public: |
+ DebugExceptionHandler(int32 pid, |
+ base::MessageLoopProxy* message_loop, |
+ const base::Closure& on_connected) |
+ : pid_(pid), message_loop_(message_loop), on_connected_(on_connected) { |
+ } |
+ |
+ virtual void ThreadMain() OVERRIDE { |
+ // In the Windows API, the set of processes being debugged is |
+ // thread-local, so we have to attach to the process (using |
+ // DebugActiveProcess()) on the same thread on which |
+ // NaClDebugLoop() receives debug events for the process. |
+ BOOL attached = false; |
+ base::ProcessHandle process_handle = base::kNullProcessHandle; |
+ if (!base::OpenProcessHandleWithAccess( |
+ pid_, |
+ base::kProcessAccessQueryInformation | |
+ base::kProcessAccessSuspendResume | |
+ base::kProcessAccessTerminate | |
+ base::kProcessAccessVMOperation | |
+ base::kProcessAccessVMRead | |
+ base::kProcessAccessVMWrite | |
+ base::kProcessAccessWaitForTermination, |
+ &process_handle)) { |
+ LOG(ERROR) << "Failed to get process handle"; |
+ } else { |
+ attached = DebugActiveProcess(pid_); |
+ if (!attached) { |
+ LOG(ERROR) << "Failed to connect to the process"; |
+ } |
+ } |
+ // At the moment we do not say in the reply whether attaching as a |
+ // debugger succeeded. In the future, when we attach on demand |
+ // when an exception handler is first registered, we can make the |
+ // NaCl syscall indicate whether attaching succeeded. |
+ message_loop_->PostTask(FROM_HERE, on_connected_); |
+ |
+ if (attached) { |
+ DWORD exit_code; |
+ NaClDebugLoop(process_handle, &exit_code); |
+ } |
+ if (process_handle != base::kNullProcessHandle) { |
+ base::CloseProcessHandle(process_handle); |
+ } |
+ delete this; |
+ } |
+ |
+ private: |
+ int32 pid_; |
+ base::MessageLoopProxy* message_loop_; |
+ base::Closure on_connected_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(DebugExceptionHandler); |
+}; |
+ |
+} // namespace |
+ |
+void NaClStartDebugExceptionHandlerThread(int32 nacl_process_id, |
+ base::MessageLoopProxy* message_loop, |
+ const base::Closure& on_connected) { |
+ // The new PlatformThread will take ownership of the |
+ // DebugExceptionHandler object, which will delete itself on exit. |
+ DebugExceptionHandler* handler = new DebugExceptionHandler( |
+ nacl_process_id, message_loop, on_connected); |
+ if (!base::PlatformThread::CreateNonJoinable(0, handler)) { |
+ on_connected.Run(); |
+ delete handler; |
+ } |
+} |