Index: shell/app_child_process.cc |
diff --git a/shell/app_child_process.cc b/shell/app_child_process.cc |
index ae52944154b980ae6c23c380e1c8f36bc0e3dda0..2beedee4719975b34b31378bc437b4a0ad2c2b45 100644 |
--- a/shell/app_child_process.cc |
+++ b/shell/app_child_process.cc |
@@ -4,6 +4,8 @@ |
#include "shell/app_child_process.h" |
+#include <unistd.h> |
+ |
#include "base/bind.h" |
#include "base/callback_helpers.h" |
#include "base/files/file_path.h" |
@@ -19,6 +21,7 @@ |
#include "base/threading/thread_checker.h" |
#include "mojo/common/message_pump_mojo.h" |
#include "mojo/edk/embedder/embedder.h" |
+#include "mojo/edk/embedder/process_delegate.h" |
#include "mojo/edk/embedder/simple_platform_support.h" |
#include "mojo/public/cpp/system/core.h" |
#include "shell/app_child_process.mojom.h" |
@@ -37,6 +40,7 @@ class Blocker { |
public: |
class Unblocker { |
public: |
+ explicit Unblocker(Blocker* blocker = nullptr) : blocker_(blocker) {} |
~Unblocker() {} |
void Unblock(base::Closure run_after) { |
@@ -44,13 +48,10 @@ class Blocker { |
DCHECK(blocker_->run_after_.is_null()); |
blocker_->run_after_ = run_after; |
blocker_->event_.Signal(); |
- blocker_ = NULL; |
+ blocker_ = nullptr; |
} |
private: |
- friend class Blocker; |
- Unblocker(Blocker* blocker) : blocker_(blocker) { DCHECK(blocker_); } |
- |
Blocker* blocker_; |
// Copy and assign allowed. |
@@ -78,11 +79,8 @@ class Blocker { |
class AppChildControllerImpl; |
-static void DestroyController(scoped_ptr<AppChildControllerImpl> controller) { |
-} |
- |
// Should be created and initialized on the main thread. |
-class AppContext { |
+class AppContext : public embedder::ProcessDelegate { |
public: |
AppContext() |
: io_thread_("io_thread"), controller_thread_("controller_thread") {} |
@@ -108,11 +106,20 @@ class AppContext { |
CHECK(controller_thread_.StartWithOptions(controller_thread_options)); |
controller_runner_ = controller_thread_.message_loop_proxy().get(); |
CHECK(controller_runner_.get()); |
+ |
+ // TODO(vtl): This should be SLAVE, not NONE. |
+ embedder::InitIPCSupport(embedder::ProcessType::NONE, controller_runner_, |
+ this, io_runner_, |
+ embedder::ScopedPlatformHandle()); |
} |
void Shutdown() { |
+ Blocker blocker; |
+ shutdown_unblocker_ = blocker.GetUnblocker(); |
controller_runner_->PostTask( |
- FROM_HERE, base::Bind(&DestroyController, base::Passed(&controller_))); |
+ FROM_HERE, base::Bind(&AppContext::ShutdownOnControllerThread, |
+ base::Unretained(this))); |
+ blocker.Block(); |
} |
base::SingleThreadTaskRunner* io_runner() const { return io_runner_.get(); } |
@@ -128,11 +135,18 @@ class AppContext { |
} |
private: |
- // Accessed only on the controller thread. |
- // IMPORTANT: This must be BEFORE |controller_thread_|, so that the controller |
- // thread gets joined (and thus |controller_| reset) before |controller_| is |
- // destroyed. |
- scoped_ptr<AppChildControllerImpl> controller_; |
+ void ShutdownOnControllerThread() { |
+ // First, destroy the controller. |
+ controller_.reset(); |
+ |
+ // Next shutdown IPC. We'll unblock the main thread in OnShutdownComplete(). |
+ embedder::ShutdownIPCSupport(); |
+ } |
+ |
+ // ProcessDelegate implementation. |
+ void OnShutdownComplete() override { |
+ shutdown_unblocker_.Unblock(base::Closure()); |
+ } |
base::Thread io_thread_; |
scoped_refptr<base::SingleThreadTaskRunner> io_runner_; |
@@ -140,6 +154,12 @@ class AppContext { |
base::Thread controller_thread_; |
scoped_refptr<base::SingleThreadTaskRunner> controller_runner_; |
+ // Accessed only on the controller thread. |
+ scoped_ptr<AppChildControllerImpl> controller_; |
+ |
+ // Used to unblock the main thread on shutdown. |
+ Blocker::Unblocker shutdown_unblocker_; |
+ |
DISALLOW_COPY_AND_ASSIGN(AppContext); |
}; |
@@ -184,7 +204,8 @@ class AppChildControllerImpl : public AppChildController, public ErrorHandler { |
void OnConnectionError() override { |
// A connection error means the connection to the shell is lost. This is not |
// recoverable. |
- CHECK(false) << "Connection error to the shell."; |
+ LOG(ERROR) << "Connection error to the shell."; |
+ _exit(1); |
} |
// |AppChildController| methods: |