Chromium Code Reviews| Index: dbus/bus.cc |
| diff --git a/dbus/bus.cc b/dbus/bus.cc |
| index 4096049417884f76044a275adbadb5e060f59636..7d235aa4b115bbe11c96844f64e60121d2c2d136 100644 |
| --- a/dbus/bus.cc |
| +++ b/dbus/bus.cc |
| @@ -24,6 +24,11 @@ namespace dbus { |
| namespace { |
| +const char kDisconnectedSignal[] = "Disconnected"; |
| +const char kDisconnectedMatchRule[] = |
| + "type='signal', path='/org/freedesktop/DBus/Local'," |
| + "interface='org.freedesktop.DBus.Local', member='Disconnected'"; |
| + |
| // The class is used for watching the file descriptor used for D-Bus |
| // communication. |
| class Watch : public base::MessagePumpLibevent::Watcher { |
| @@ -364,6 +369,10 @@ bool Bus::Connect() { |
| // We shouldn't exit on the disconnected signal. |
| dbus_connection_set_exit_on_disconnect(connection_, false); |
| + // Watch Disconnected signal. |
| + AddFilterFunction(Bus::OnConnectionDisconnectedFilter, this); |
| + AddMatch(kDisconnectedMatchRule, error.get()); |
| + |
| return true; |
| } |
| @@ -704,9 +713,12 @@ void Bus::ProcessAllIncomingDataIfAny() { |
| AssertOnDBusThread(); |
| // As mentioned at the class comment in .h file, connection_ can be NULL. |
| - if (!connection_ || !dbus_connection_get_is_connected(connection_)) |
| + if (!connection_) |
| return; |
| + // It is safe and necessary to call dbus_connection_get_dispatch_status even |
| + // if the connection is lost. Otherwise we will miss "Disconnected" signal. |
| + // (crbug.com/174431) |
| if (dbus_connection_get_dispatch_status(connection_) == |
| DBUS_DISPATCH_DATA_REMAINS) { |
| while (dbus_connection_dispatch(connection_) == |
| @@ -842,9 +854,6 @@ void Bus::OnDispatchStatusChanged(DBusConnection* connection, |
| DCHECK_EQ(connection, connection_); |
| AssertOnDBusThread(); |
| - if (!dbus_connection_get_is_connected(connection)) |
| - return; |
| - |
| // We cannot call ProcessAllIncomingDataIfAny() here, as calling |
| // dbus_connection_dispatch() inside DBusDispatchStatusFunction is |
| // prohibited by the D-Bus library. Hence, we post a task here instead. |
| @@ -854,6 +863,16 @@ void Bus::OnDispatchStatusChanged(DBusConnection* connection, |
| this)); |
| } |
| +void Bus::OnConnectionDisconnected(DBusConnection* connection) { |
|
satorux1
2013/02/06 03:15:39
on what thread this function is called? Please ann
Seigo Nonaka
2013/02/06 04:57:22
Done.
|
| + if (!connection) |
| + return; |
| + |
| + DCHECK_EQ(connection, connection_); |
| + DCHECK(!dbus_connection_get_is_connected(connection)); |
| + |
| + ShutdownAndBlock(); |
| +} |
| + |
| dbus_bool_t Bus::OnAddWatchThunk(DBusWatch* raw_watch, void* data) { |
| Bus* self = static_cast<Bus*>(data); |
| return self->OnAddWatch(raw_watch); |
| @@ -891,4 +910,18 @@ void Bus::OnDispatchStatusChangedThunk(DBusConnection* connection, |
| self->OnDispatchStatusChanged(connection, status); |
| } |
| +DBusHandlerResult Bus::OnConnectionDisconnectedFilter( |
| + DBusConnection *connection, |
| + DBusMessage *message, |
| + void *data) { |
|
satorux1
2013/02/06 03:15:39
ditto. please annotate the thread.
Seigo Nonaka
2013/02/06 04:57:22
Done.
|
| + if (dbus_message_is_signal(message, |
| + DBUS_INTERFACE_LOCAL, |
| + kDisconnectedSignal)) { |
| + Bus* self = static_cast<Bus*>(data); |
| + self->OnConnectionDisconnected(connection); |
| + return DBUS_HANDLER_RESULT_HANDLED; |
| + } |
| + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
| +} |
| + |
| } // namespace dbus |