throw FatalException();
dbus_connection_set_wakeup_main_function(conn, wakeup_main, this, NULL);
+
+ add_match("type='signal', interface='" DBUS_INTERFACE_DBUS "', member='NameOwnerChanged'");
}
}
}
- int timeout = -1;
+ int timeout = periodic_timeout();
if (idle_timeout >= 0)
{
if (r == -1)
throw FatalException();
+ periodic();
+
{
for (vector<struct pollfd>::const_iterator it2 = pollfds.begin(); it2 != pollfds.end(); ++it2)
{
}
}
- while (get_dispatch_status() == DBUS_DISPATCH_DATA_REMAINS)
+ DBusMessage* tmp = pop_message();
+ if (tmp)
{
- dispatch();
+ DBus::Message msg(tmp, false);
+ dispatch_incoming(msg);
}
if (idle_timeout >= 0)
write(s->wakeup_pipe[1], &arbitrary, 1);
}
+
+ void
+ DBus::MainLoop::dispatch_incoming(Message& msg)
+ {
+ switch (msg.get_type())
+ {
+ case DBUS_MESSAGE_TYPE_METHOD_CALL:
+ {
+ method_call(msg);
+ }
+ break;
+
+ case DBUS_MESSAGE_TYPE_SIGNAL:
+ {
+ signal(msg);
+
+ if (msg.is_signal(DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
+ {
+ string name, old_owner, new_owner;
+
+ DBus::Hihi hihi(msg);
+ hihi >> name >> old_owner >> new_owner;
+
+ if (name == new_owner && old_owner.empty())
+ client_connected(name);
+
+ if (name == old_owner && new_owner.empty())
+ client_disconnected(name);
+ }
+ }
+ break;
+ }
+ }
+
}
s << " name:'" << it->name << "'";
if (&*it == this)
s << " myself";
+ if (it->zombie)
+ s << " zombie";
if (!it->locks.empty())
s << " locks:'" << boost::join(it->locks, ",") << "'";
if (!it->comparisons.empty())
}
-Clients::iterator
-client_connected(const string& name)
-{
- return clients.add(name);
-}
-
-
-void
-client_disconnected(const string& name)
-{
- clients.remove(name);
-}
-
-
void
Client::dispatch(DBus::Connection& conn, DBus::Message& msg)
{
}
-void
-unregister_func(DBusConnection* connection, void* data)
+class MyMainLoop : public DBus::MainLoop
+{
+public:
+
+ MyMainLoop(DBusBusType type);
+ ~MyMainLoop();
+
+ void method_call(DBus::Message& message);
+ void signal(DBus::Message& message);
+ void client_connected(const string& name);
+ void client_disconnected(const string& name);
+ void periodic();
+ int periodic_timeout();
+
+};
+
+
+MyMainLoop::MyMainLoop(DBusBusType type)
+ : MainLoop(type)
{
}
-DBusHandlerResult
-message_func1(DBusConnection* connection, DBusMessage* message, void* data)
+MyMainLoop::~MyMainLoop()
{
- DBus::MainLoop* s = static_cast<DBus::MainLoop*>(data);
+}
- DBus::Message msg(message, true);
- if (msg.get_type() == DBUS_MESSAGE_TYPE_METHOD_CALL)
- {
- y2deb("method call sender:'" << msg.get_sender() << "' path:'" <<
- msg.get_path() << "' interface:'" << msg.get_interface() <<
- "' member:'" << msg.get_member() << "'");
+void
+MyMainLoop::method_call(DBus::Message& msg)
+{
+ y2deb("method call sender:'" << msg.get_sender() << "' path:'" <<
+ msg.get_path() << "' interface:'" << msg.get_interface() <<
+ "' member:'" << msg.get_member() << "'");
- s->reset_idle_count();
+ reset_idle_count();
- if (msg.is_method_call(DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
- {
- Client::introspect(*s, msg);
- }
- else
+ if (msg.is_method_call(DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
+ {
+ Client::introspect(*this, msg);
+ }
+ else
+ {
+ boost::unique_lock<boost::shared_mutex> lock(big_mutex);
+
+ Clients::iterator client = clients.find(msg.get_sender());
+ if (client == clients.end())
{
- Clients::iterator client = clients.find(msg.get_sender());
- if (client == clients.end())
- {
- y2deb("client connected invisible '" << msg.get_sender() << "'");
- client = client_connected(msg.get_sender());
- s->set_idle_timeout(-1);
- }
-
- client->add_task(*s, msg);
+ y2deb("client connected invisible '" << msg.get_sender() << "'");
+ client = clients.add(msg.get_sender());
+ set_idle_timeout(-1);
}
- return DBUS_HANDLER_RESULT_HANDLED;
+ client->add_task(*this, msg);
}
+}
+
+
+void
+MyMainLoop::signal(DBus::Message& msg)
+{
+ y2deb("signal sender:'" << msg.get_sender() << "' path:'" <<
+ msg.get_path() << "' interface:'" << msg.get_interface() <<
+ "' member:'" << msg.get_member() << "'");
+}
+
+
+void
+MyMainLoop::client_connected(const string& name)
+{
+ y2deb("client connected '" << name << "'");
+
+ boost::unique_lock<boost::shared_mutex> lock(big_mutex);
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ clients.add(name);
+
+ reset_idle_count();
+ set_idle_timeout(-1);
}
-DBusHandlerResult
-message_func2(DBusConnection* connection, DBusMessage* message, void* data)
+void
+MyMainLoop::client_disconnected(const string& name)
{
- DBus::MainLoop* s = static_cast<DBus::MainLoop*>(data);
+ y2deb("client disconnected '" << name << "'");
- DBus::Message msg(message, true);
+ boost::unique_lock<boost::shared_mutex> lock(big_mutex);
- if (msg.get_type() == DBUS_MESSAGE_TYPE_SIGNAL)
+ Clients::iterator client = clients.find(name);
+ if (client != clients.end())
{
- y2deb("signal sender:'" << msg.get_sender() << "' path:'" <<
- msg.get_path() << "' interface:'" << msg.get_interface() <<
- "' member:'" << msg.get_member() << "'");
-
- if (msg.is_signal(DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
- {
- string name, old_owner, new_owner;
-
- DBus::Hihi hihi(msg);
- hihi >> name >> old_owner >> new_owner;
-
- if (name == new_owner && old_owner.empty())
- {
- y2deb("client connected '" << name << "'");
- client_connected(name);
- s->reset_idle_count();
- s->set_idle_timeout(-1);
- }
-
- if (name == old_owner && new_owner.empty())
- {
- y2deb("client disconnected '" << name << "'");
- client_disconnected(name);
- s->reset_idle_count();
- if (clients.empty())
- s->set_idle_timeout(30);
- }
-
- return DBUS_HANDLER_RESULT_HANDLED;
- }
+ client->zombie = true;
+ client->thread.interrupt();
}
+ reset_idle_count();
+}
+
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+void
+MyMainLoop::periodic()
+{
+ y2deb("periodic");
+
+ boost::unique_lock<boost::shared_mutex> lock(big_mutex);
+
+ clients.remove_zombies();
+
+ if (clients.empty())
+ {
+ y2deb("no clients left");
+ set_idle_timeout(30);
+ }
}
-DBusObjectPathVTable dbus_vtable1 = {
- unregister_func, message_func1, NULL, NULL, NULL, NULL
-};
+int
+MyMainLoop::periodic_timeout()
+{
+ boost::unique_lock<boost::shared_mutex> lock(big_mutex);
-DBusObjectPathVTable dbus_vtable2 = {
- unregister_func, message_func2, NULL, NULL, NULL, NULL
-};
+ if (clients.has_zombies())
+ return 1000;
+
+ return -1;
+}
void
dbus_threads_init_default();
- DBus::MainLoop mainloop(DBUS_BUS_SYSTEM);
+ MyMainLoop mainloop(DBUS_BUS_SYSTEM);
mainloop.set_idle_timeout(30);
y2mil("Listening for method calls and signals");
- mainloop.register_object_path(PATH, &dbus_vtable1, &mainloop);
- mainloop.register_object_path(DBUS_PATH_DBUS, &dbus_vtable2, &mainloop);
- mainloop.add_match("type='signal', interface='" DBUS_INTERFACE_DBUS "', member='NameOwnerChanged'");
-
mainloop.run();
y2mil("Exiting");