| Index: dbus/bus.cc
|
| diff --git a/dbus/bus.cc b/dbus/bus.cc
|
| index 1b766acd0f7a787b1f17da1fbb7c8f517b8f57ad..36513320d3024a060e1c5bf65ed9f752545e9d11 100644
|
| --- a/dbus/bus.cc
|
| +++ b/dbus/bus.cc
|
| @@ -14,6 +14,7 @@
|
| #include "base/stl_util.h"
|
| #include "base/threading/thread.h"
|
| #include "base/threading/thread_restrictions.h"
|
| +#include "base/time.h"
|
| #include "dbus/exported_object.h"
|
| #include "dbus/object_proxy.h"
|
| #include "dbus/scoped_dbus_error.h"
|
| @@ -178,11 +179,13 @@ Bus::Bus(const Options& options)
|
| : bus_type_(options.bus_type),
|
| connection_type_(options.connection_type),
|
| dbus_thread_(options.dbus_thread),
|
| + on_shutdown_(false /* manual_reset */, false /* initially_signaled */),
|
| connection_(NULL),
|
| origin_loop_(MessageLoop::current()),
|
| origin_thread_id_(base::PlatformThread::CurrentId()),
|
| dbus_thread_id_(base::kInvalidThreadId),
|
| async_operations_set_up_(false),
|
| + shutdown_completed_(false),
|
| num_pending_watches_(0),
|
| num_pending_timeouts_(0) {
|
| if (dbus_thread_) {
|
| @@ -299,21 +302,31 @@ void Bus::ShutdownAndBlock() {
|
| }
|
|
|
| // Private connection should be closed.
|
| - if (connection_ && connection_type_ == PRIVATE) {
|
| - dbus_connection_close(connection_);
|
| + if (connection_) {
|
| + if (connection_type_ == PRIVATE)
|
| + dbus_connection_close(connection_);
|
| + // dbus_connection_close() won't unref.
|
| + dbus_connection_unref(connection_);
|
| }
|
| - // dbus_connection_close() won't unref.
|
| - dbus_connection_unref(connection_);
|
|
|
| connection_ = NULL;
|
| + shutdown_completed_ = true;
|
| }
|
|
|
| -void Bus::Shutdown(OnShutdownCallback callback) {
|
| +void Bus::ShutdownOnDBusThreadAndBlock() {
|
| AssertOnOriginThread();
|
| + DCHECK(dbus_thread_);
|
|
|
| - PostTaskToDBusThread(FROM_HERE, base::Bind(&Bus::ShutdownInternal,
|
| - this,
|
| - callback));
|
| + PostTaskToDBusThread(FROM_HERE, base::Bind(
|
| + &Bus::ShutdownOnDBusThreadAndBlockInternal,
|
| + this));
|
| +
|
| + // Wait until the shutdown is complete on the D-Bus thread.
|
| + // The shutdown should not hang, but set timeout just in case.
|
| + const int kTimeoutSecs = 3;
|
| + const base::TimeDelta timeout(base::TimeDelta::FromSeconds(kTimeoutSecs));
|
| + const bool signaled = on_shutdown_.TimedWait(timeout);
|
| + LOG_IF(ERROR, !signaled) << "Failed to shutdown the bus";
|
| }
|
|
|
| bool Bus::RequestOwnership(const std::string& service_name) {
|
| @@ -535,11 +548,11 @@ void Bus::UnregisterObjectPath(const std::string& object_path) {
|
| registered_object_paths_.erase(object_path);
|
| }
|
|
|
| -void Bus::ShutdownInternal(OnShutdownCallback callback) {
|
| +void Bus::ShutdownOnDBusThreadAndBlockInternal() {
|
| AssertOnDBusThread();
|
|
|
| ShutdownAndBlock();
|
| - PostTaskToOriginThread(FROM_HERE, callback);
|
| + on_shutdown_.Signal();
|
| }
|
|
|
| void Bus::ProcessAllIncomingDataIfAny() {
|
|
|