// Copyright 2013 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 "components/nacl/common/nacl_debug_exception_handler_win.h" #include "base/bind.h" #include "base/threading/platform_thread.h" #include "base/win/scoped_handle.h" #include "native_client/src/public/win/debug_exception_handler.h" namespace { class DebugExceptionHandler : public base::PlatformThread::Delegate { public: DebugExceptionHandler(base::Process nacl_process, const std::string& startup_info, scoped_refptr task_runner, const base::Callback& on_connected) : nacl_process_(nacl_process.Pass()), startup_info_(startup_info), task_runner_(task_runner), on_connected_(on_connected) {} 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 // NaClDebugExceptionHandlerRun() receives debug events for the // process. bool attached = false; int pid = nacl_process_.Pid(); if (nacl_process_.IsValid()) { DCHECK(pid); if (!DebugActiveProcess(pid)) { LOG(ERROR) << "Failed to connect to the process"; } else { attached = true; } } else { LOG(ERROR) << "Invalid process handle"; } task_runner_->PostTask(FROM_HERE, base::Bind(on_connected_, attached)); if (attached) { NaClDebugExceptionHandlerRun( nacl_process_.Handle(), reinterpret_cast(startup_info_.data()), startup_info_.size()); } delete this; } private: base::Process nacl_process_; std::string startup_info_; const scoped_refptr task_runner_; base::Callback on_connected_; DISALLOW_COPY_AND_ASSIGN(DebugExceptionHandler); }; } // namespace void NaClStartDebugExceptionHandlerThread( base::Process nacl_process, const std::string& startup_info, scoped_refptr task_runner, const base::Callback& on_connected) { // The new PlatformThread will take ownership of the // DebugExceptionHandler object, which will delete itself on exit. DebugExceptionHandler* handler = new DebugExceptionHandler( nacl_process.Pass(), startup_info, task_runner, on_connected); if (!base::PlatformThread::CreateNonJoinable(0, handler)) { on_connected.Run(false); delete handler; } }