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() { |