From e742f63e9c56cc2c913fa8cfda7a9d583a2c2aa2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 27 Jan 2010 16:26:01 +0100 Subject: abrtd: proper fix to autostart problem Signed-off-by: Denys Vlasenko --- lib/Utils/abrt_dbus.cpp | 8 +++----- src/Applet/Applet.cpp | 8 ++++++++ src/Daemon/CommLayerServerDBus.cpp | 11 +++++++++++ src/Daemon/Daemon.cpp | 21 ++++++++++++--------- src/Gui/CCDBusBackend.py | 8 +++----- 5 files changed, 37 insertions(+), 19 deletions(-) diff --git a/lib/Utils/abrt_dbus.cpp b/lib/Utils/abrt_dbus.cpp index ad23d56c..8423e66c 100644 --- a/lib/Utils/abrt_dbus.cpp +++ b/lib/Utils/abrt_dbus.cpp @@ -148,7 +148,7 @@ static gboolean handle_dbus_fd(GIOChannel *gio, GIOCondition condition, gpointer while (dbus_connection_dispatch(g_dbus_conn) == DBUS_DISPATCH_DATA_REMAINS) VERB3 log("%s: more data to process, looping", __func__); - return TRUE; /* "glib, do not remove this even source!" */ + return TRUE; /* "glib, do not remove this event source!" */ } struct watch_app_info_t @@ -170,10 +170,8 @@ static void toggled_watch(DBusWatch *watch, void* data) app_info->watch_enabled = true; int dbus_flags = dbus_watch_get_flags(watch); int glib_flags = 0; - if (dbus_flags & DBUS_WATCH_READABLE) - glib_flags |= G_IO_IN; - if (dbus_flags & DBUS_WATCH_WRITABLE) - glib_flags |= G_IO_OUT; + if (dbus_flags & DBUS_WATCH_READABLE) glib_flags |= G_IO_IN; + if (dbus_flags & DBUS_WATCH_WRITABLE) glib_flags |= G_IO_OUT; VERB3 log(" adding watch to glib main loop. dbus_flags:%x glib_flags:%x", dbus_flags, glib_flags); app_info->event_source_id = g_io_add_watch(app_info->channel, GIOCondition(glib_flags), handle_dbus_fd, watch); } diff --git a/src/Applet/Applet.cpp b/src/Applet/Applet.cpp index 550e1aac..b17a88b7 100644 --- a/src/Applet/Applet.cpp +++ b/src/Applet/Applet.cpp @@ -255,6 +255,14 @@ int main(int argc, char** argv) applet->Disable(msg); } + /* dbus_bus_request_name can already read some data. Thus while dbus fd hasn't + * any data anymore, dbus library can buffer a message or two. + * If we don't do this, the data won't be processed until next dbus data arrives. + */ + int cnt = 10; + while (dbus_connection_dispatch(system_conn) != DBUS_DISPATCH_COMPLETE && --cnt) + continue; + /* Enter main loop */ gtk_main(); diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp index f1f10e50..f2471586 100644 --- a/src/Daemon/CommLayerServerDBus.cpp +++ b/src/Daemon/CommLayerServerDBus.cpp @@ -565,6 +565,17 @@ CCommLayerServerDBus::CCommLayerServerDBus() //maybe check that r == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER instead? handle_dbus_err(rc < 0, &err); VERB3 log("dbus init done"); + + /* dbus_bus_request_name can already read some data. For example, + * if we were autostarted, the call which caused autostart arrives + * at this moment. Thus while dbus fd hasn't any data anymore, + * dbus library can buffer a message or two. + * If we don't do this, the data won't be processed + * until next dbus data arrives. + */ + int cnt = 10; + while (dbus_connection_dispatch(conn) != DBUS_DISPATCH_COMPLETE && --cnt) + VERB3 log("processed initial buffered dbus message"); } CCommLayerServerDBus::~CCommLayerServerDBus() diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 83b1ceef..5bcbe232 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -797,15 +797,6 @@ int main(int argc, char** argv) if (SetUpCron() != 0) throw 1; -#if 1 //def ENABLE_DBUS - VERB1 log("Initializing dbus"); - g_pCommLayer = new CCommLayerServerDBus(); -#elif ENABLE_SOCKET - g_pCommLayer = new CCommLayerServerSocket(); -#endif - if (g_pCommLayer->m_init_error) - throw 1; - VERB1 log("Adding inotify watch to glib main loop"); pGiochannel_inotify = g_io_channel_unix_new(inotify_fd); g_io_add_watch(pGiochannel_inotify, G_IO_IN, handle_inotify_cb, NULL); @@ -824,6 +815,18 @@ int main(int argc, char** argv) if (CreatePidFile() != 0) throw 1; pidfile_created = true; + + /* Note: this already may process a few dbus messages, + * therefore it should be the last thing to initialize. + */ +#if 1 //def ENABLE_DBUS + VERB1 log("Initializing dbus"); + g_pCommLayer = new CCommLayerServerDBus(); +#elif ENABLE_SOCKET + g_pCommLayer = new CCommLayerServerSocket(); +#endif + if (g_pCommLayer->m_init_error) + throw 1; } catch (...) { diff --git a/src/Gui/CCDBusBackend.py b/src/Gui/CCDBusBackend.py index b99e6f8e..1ab0e3a8 100644 --- a/src/Gui/CCDBusBackend.py +++ b/src/Gui/CCDBusBackend.py @@ -99,11 +99,9 @@ class DBusManager(gobject.GObject): # Autostart hack # Theoretically, this is not needed, the first dbus call # should autostart daemon if needed. In practice, - # without this code autostart is not reliable. Apparently - # dbus fails to check that the first call after autostart - # does not fail because daemon did not finish its initialization yet. - # (strace says abrt-gui -> dbus_daemon transfer is ok, - # I suspect dbus_daemon -> freshly_started_abrtd isn't) + # without this code autostart is not reliable. + # Update: fixed the problem on daemon side, + # but retaining this code for now. More stability won't hurt us... try: (always_true, rc) = self.bus.start_service_by_name(ABRTD_DBUS_NAME, flags=0) # rc is either self.bus.START_REPLY_SUCCESS or self.bus.START_REPLY_ALREADY_RUNNING -- cgit