diff options
-rw-r--r-- | inc/abrtlib.h | 11 | ||||
-rw-r--r-- | lib/Utils/abrt_dbus.cpp | 202 | ||||
-rw-r--r-- | lib/Utils/abrt_dbus.h | 10 | ||||
-rw-r--r-- | lib/Utils/logging.cpp | 2 | ||||
-rw-r--r-- | src/Applet/Makefile.am | 6 | ||||
-rw-r--r-- | src/Daemon/CommLayerServerDBus.cpp | 183 | ||||
-rw-r--r-- | src/Daemon/Daemon.cpp | 1 | ||||
-rw-r--r-- | src/Daemon/Daemon.h | 10 |
8 files changed, 230 insertions, 195 deletions
diff --git a/inc/abrtlib.h b/inc/abrtlib.h index 1affdf91..c99f4b7e 100644 --- a/inc/abrtlib.h +++ b/inc/abrtlib.h @@ -83,6 +83,17 @@ extern void verror_msg(const char *s, va_list p, const char *strerr); #undef log #define log(...) error_msg(__VA_ARGS__) +/* Verbosity level */ +extern int g_verbose; +/* VERB1 log("what you sometimes want to see, even on a production box") */ +#define VERB1 if (g_verbose >= 1) +/* VERB2 log("debug message, not going into insanely small details") */ +#define VERB2 if (g_verbose >= 2) +/* VERB3 log("lots and lots of details") */ +#define VERB3 if (g_verbose >= 3) +/* there is no level > 3 */ + + void* xmalloc(size_t size); void* xrealloc(void *ptr, size_t size); void* xzalloc(size_t size); diff --git a/lib/Utils/abrt_dbus.cpp b/lib/Utils/abrt_dbus.cpp index 3d868b9d..37d6d3e6 100644 --- a/lib/Utils/abrt_dbus.cpp +++ b/lib/Utils/abrt_dbus.cpp @@ -1,9 +1,11 @@ #include <dbus/dbus.h> +#include <glib.h> #include "abrtlib.h" #include "abrt_dbus.h" DBusConnection* g_dbus_conn; + /* * Helpers for building DBus messages */ @@ -40,6 +42,7 @@ void store_string(DBusMessageIter* iter, const char* val) die_out_of_memory(); } + /* * Helpers for parsing DBus messages */ @@ -110,3 +113,202 @@ int load_charp(DBusMessageIter* iter, const char*& val) //log("load_charp:'%s'", val); return dbus_message_iter_next(iter); } + + +/* + * Glib integration machinery + */ + +/* Callback: "glib says dbus fd is active" */ +static gboolean handle_dbus_fd(GIOChannel *gio, GIOCondition condition, gpointer data) +{ + DBusWatch *watch = (DBusWatch*)data; + + VERB3 log("%s(gio, condition:%x [bits:IN/PRI/OUT/ERR/HUP...], data)", __func__, int(condition)); + + /* Notify the D-Bus library when a previously-added watch + * is ready for reading or writing, or has an exception such as a hangup. + */ + int glib_flags = int(condition); + int dbus_flags = 0; + if (glib_flags & G_IO_IN) dbus_flags |= DBUS_WATCH_READABLE; + if (glib_flags & G_IO_OUT) dbus_flags |= DBUS_WATCH_WRITABLE; + if (glib_flags & G_IO_ERR) dbus_flags |= DBUS_WATCH_ERROR; + if (glib_flags & G_IO_HUP) dbus_flags |= DBUS_WATCH_HANGUP; + /* + * TODO: + * If dbus_watch_handle returns FALSE, then the file descriptor + * may still be ready for reading or writing, but more memory + * is needed in order to do the reading or writing. If you ignore + * the FALSE return, your application may spin in a busy loop + * on the file descriptor until memory becomes available, + * but nothing more catastrophic should happen. + */ + dbus_watch_handle(watch, dbus_flags); + + 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!" */ +} + +struct watch_app_info_t +{ + GIOChannel *channel; + guint event_source_id; + bool watch_enabled; +}; +/* Callback: "dbus_watch_get_enabled() may return a different value than it did before" */ +static void toggled_watch(DBusWatch *watch, void* data) +{ + VERB3 log("%s(watch:%p, data)", __func__, watch); + + watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); + if (dbus_watch_get_enabled(watch)) + { + if (!app_info->watch_enabled) + { + 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; + 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); + } + /* else: it was already enabled */ + } else { + if (app_info->watch_enabled) + { + app_info->watch_enabled = false; + /* does it free the hidden GSource too? */ + VERB3 log(" removing watch from glib main loop"); + g_source_remove(app_info->event_source_id); + } + /* else: it was already disabled */ + } +} +/* Callback: "libdbus needs a new watch to be monitored by the main loop" */ +static dbus_bool_t add_watch(DBusWatch *watch, void* data) +{ + VERB3 log("%s(watch:%p, data)", __func__, watch); + + watch_app_info_t* app_info = (watch_app_info_t*)xzalloc(sizeof(*app_info)); + dbus_watch_set_data(watch, app_info, free); + + int fd = dbus_watch_get_unix_fd(watch); + VERB3 log(" dbus_watch_get_unix_fd():%d", fd); + app_info->channel = g_io_channel_unix_new(fd); + /* _unconditionally_ adding it to event loop would be an error */ + toggled_watch(watch, data); + return TRUE; +} +/* Callback: "libdbus no longer needs a watch to be monitored by the main loop" */ +static void remove_watch(DBusWatch *watch, void* data) +{ + VERB3 log("%s()", __func__); + watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); + if (app_info->watch_enabled) + { + app_info->watch_enabled = false; + g_source_remove(app_info->event_source_id); + } + g_io_channel_unref(app_info->channel); +} + +/* Callback: "libdbus needs a new timeout to be monitored by the main loop" */ +static dbus_bool_t add_timeout(DBusTimeout *timeout, void* data) +{ + VERB3 log("%s()", __func__); + return TRUE; +} +/* Callback: "libdbus no longer needs a timeout to be monitored by the main loop" */ +static void remove_timeout(DBusTimeout *timeout, void* data) +{ + VERB3 log("%s()", __func__); +} +/* Callback: "dbus_timeout_get_enabled() may return a different value than it did before" */ +static void timeout_toggled(DBusTimeout *timeout, void* data) +{ +//seems to be never called, let's make it noisy + error_msg_and_die("%s(): FIXME: some dbus machinery is missing here", __func__); +} + +/* Callback: "DBusObjectPathVTable is unregistered (or its connection is freed)" */ +static void unregister_vtable(DBusConnection *conn, void* data) +{ + VERB3 log("%s()", __func__); +} + +/* + * Initialization works as follows: + * + * we have a DBusConnection* (say, obtained with dbus_bus_get) + * we call dbus_connection_set_watch_functions + * libdbus calls back add_watch(watch:0x2341090, data), this watch is for writing + * we call toggled_watch, but it finds that watch is not to be enabled yet + * libdbus calls back add_watch(watch:0x23410e0, data), this watch is for reading + * we call toggled_watch, it adds watch's fd to glib main loop with POLLIN + * (note: these watches are different objects, but they have the same fd) + * we call dbus_connection_set_timeout_functions + * we call dbus_connection_register_object_path + * + * Note: if user will later call dbus_bus_request_name(conn, ...): + * libdbus calls back add_timeout() + * libdbus calls back remove_timeout() + * note - no callback to timeout_toggled()! + * (therefore there is no code yet in timeout_toggled (see above), it's not used) + */ +void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, + const char* object_path, + DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) +) { +//do we need this? why? +//log("dbus_connection_set_dispatch_status_function"); +// dbus_connection_set_dispatch_status_function(conn, +// dispatch, /* void dispatch(DBusConnection *conn, DBusDispatchStatus new_status, void* data) */ +// NULL, /* data */ +// NULL /* free_data_function */ +// ) + VERB3 log("dbus_connection_set_watch_functions"); + if (!dbus_connection_set_watch_functions(conn, + add_watch, + remove_watch, + toggled_watch, + NULL, /* data */ + NULL /* free_data_function */ + ) + ) { + die_out_of_memory(); + } + VERB3 log("dbus_connection_set_timeout_functions"); + if (!dbus_connection_set_timeout_functions(conn, + add_timeout, + remove_timeout, + timeout_toggled, + NULL, /* data */ + NULL /* free_data_function */ + ) + ) { + die_out_of_memory(); + } + + if (object_path && message_received_func) + { + /* Table */ + const DBusObjectPathVTable vtable = { + /* .unregister_function = */ unregister_vtable, + /* .message_function = */ message_received_func, + }; + VERB3 log("dbus_connection_register_object_path"); + if (!dbus_connection_register_object_path(conn, + object_path, + &vtable, + NULL /* data */ + ) + ) { + die_out_of_memory(); + } + } +} diff --git a/lib/Utils/abrt_dbus.h b/lib/Utils/abrt_dbus.h index e2bf9fbf..731f1c10 100644 --- a/lib/Utils/abrt_dbus.h +++ b/lib/Utils/abrt_dbus.h @@ -6,6 +6,16 @@ extern DBusConnection* g_dbus_conn; /* + * Glib integration machinery + */ +void attach_dbus_conn_to_glib_main_loop(DBusConnection* conn, + const char* object_path_to_register = NULL, /* NULL if you are just a client */ + /* makes sense only if you use object_path_to_register: */ + DBusHandlerResult (*message_received_func)(DBusConnection *conn, DBusMessage *msg, void* data) = NULL +); + + +/* * Helpers for building DBus messages */ diff --git a/lib/Utils/logging.cpp b/lib/Utils/logging.cpp index d79ded5d..f70d23f3 100644 --- a/lib/Utils/logging.cpp +++ b/lib/Utils/logging.cpp @@ -8,6 +8,8 @@ int xfunc_error_retval = EXIT_FAILURE; +int g_verbose; + void xfunc_die(void) { exit(xfunc_error_retval); diff --git a/src/Applet/Makefile.am b/src/Applet/Makefile.am index accca397..67c17766 100644 --- a/src/Applet/Makefile.am +++ b/src/Applet/Makefile.am @@ -23,13 +23,13 @@ abrt_applet_CPPFLAGS = \ # $(DBUS_CFLAGS) # $(DBUS_GLIB_CFLAGS) abrt_applet_LDADD = \ - ../../lib/Utils/libABRTUtils.la \ -lglib-2.0 \ -lgthread-2.0 \ - $(DL_LIBS) \ - $(GTK_LIBS) \ $(DBUSCPP_LIBS) \ $(LIBNOTIFY_LIBS) +# ../../lib/Utils/libABRTUtils.la +# $(DL_LIBS) +# $(GTK_LIBS) EXTRA_DIST = abrt-applet.desktop popup.GtkBuilder diff --git a/src/Daemon/CommLayerServerDBus.cpp b/src/Daemon/CommLayerServerDBus.cpp index 2f88a72b..08cd3d5e 100644 --- a/src/Daemon/CommLayerServerDBus.cpp +++ b/src/Daemon/CommLayerServerDBus.cpp @@ -1,4 +1,3 @@ -//#include <iostream> #include <dbus/dbus.h> #include "abrtlib.h" #include "abrt_dbus.h" @@ -430,121 +429,6 @@ static int handle_SetSettings(DBusMessage* call, DBusMessage* reply) * Glib integration machinery */ -/* Callback: "glib says dbus fd is active" */ -static gboolean handle_dbus(GIOChannel *gio, GIOCondition condition, gpointer data) -{ - DBusWatch *watch = (DBusWatch*)data; - - VERB3 log("%s(gio, condition:%x [bits:IN/PRI/OUT/ERR/HUP...], data)", __func__, int(condition)); - - /* Notify the D-Bus library when a previously-added watch - * is ready for reading or writing, or has an exception such as a hangup. - */ - int glib_flags = int(condition); - int dbus_flags = 0; - if (glib_flags & G_IO_IN) dbus_flags |= DBUS_WATCH_READABLE; - if (glib_flags & G_IO_OUT) dbus_flags |= DBUS_WATCH_WRITABLE; - if (glib_flags & G_IO_ERR) dbus_flags |= DBUS_WATCH_ERROR; - if (glib_flags & G_IO_HUP) dbus_flags |= DBUS_WATCH_HANGUP; - /* - * TODO: - * If dbus_watch_handle returns FALSE, then the file descriptor - * may still be ready for reading or writing, but more memory - * is needed in order to do the reading or writing. If you ignore - * the FALSE return, your application may spin in a busy loop - * on the file descriptor until memory becomes available, - * but nothing more catastrophic should happen. - */ - dbus_watch_handle(watch, dbus_flags); - - 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!" */ -} -struct watch_app_info_t -{ - GIOChannel *channel; - guint event_source_id; - bool watch_enabled; -}; -/* Callback: "dbus_watch_get_enabled() may return a different value than it did before" */ -static void toggled_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s(watch:%p, data)", __func__, watch); - - watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); - if (dbus_watch_get_enabled(watch)) - { - if (!app_info->watch_enabled) - { - 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; - 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, watch); - } - /* else: it was already enabled */ - } else { - if (app_info->watch_enabled) - { - app_info->watch_enabled = false; - /* does it free the hidden GSource too? */ - VERB3 log(" removing watch from glib main loop"); - g_source_remove(app_info->event_source_id); - } - /* else: it was already disabled */ - } -} -/* Callback: "libdbus needs a new watch to be monitored by the main loop" */ -static dbus_bool_t add_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s(watch:%p, data)", __func__, watch); - - watch_app_info_t* app_info = (watch_app_info_t*)xzalloc(sizeof(*app_info)); - dbus_watch_set_data(watch, app_info, free); - - int fd = dbus_watch_get_unix_fd(watch); - VERB3 log(" dbus_watch_get_unix_fd():%d", fd); - app_info->channel = g_io_channel_unix_new(fd); - /* _unconditionally_ adding it to event loop would be an error */ - toggled_watch(watch, data); - return TRUE; -} -/* Callback: "libdbus no longer needs a watch to be monitored by the main loop" */ -static void remove_watch(DBusWatch *watch, void* data) -{ - VERB3 log("%s()", __func__); - watch_app_info_t* app_info = (watch_app_info_t*)dbus_watch_get_data(watch); - if (app_info->watch_enabled) - { - app_info->watch_enabled = false; - g_source_remove(app_info->event_source_id); - } - g_io_channel_unref(app_info->channel); -} - -/* Callback: "libdbus needs a new timeout to be monitored by the main loop" */ -static dbus_bool_t add_timeout(DBusTimeout *timeout, void* data) -{ - VERB3 log("%s()", __func__); - return TRUE; -} -/* Callback: "libdbus no longer needs a timeout to be monitored by the main loop" */ -static void remove_timeout(DBusTimeout *timeout, void* data) -{ - VERB3 log("%s()", __func__); -} -/* Callback: "dbus_timeout_get_enabled() may return a different value than it did before" */ -static void timeout_toggled(DBusTimeout *timeout, void* data) -{ -//seems to be never called, let's make it noisy - log("%s()", __func__); -} - /* Callback: "a message is received to a registered object path" */ static DBusHandlerResult message_received(DBusConnection *conn, DBusMessage *msg, void* data) { @@ -603,16 +487,6 @@ static DBusHandlerResult message_received(DBusConnection *conn, DBusMessage *msg return DBUS_HANDLER_RESULT_HANDLED; } -/* Callback: "DBusObjectPathVTable is unregistered (or its connection is freed)" */ -static void unregister_vtable(DBusConnection *conn, void* data) -{ - VERB3 log("%s()", __func__); -} -/* Table */ -static const DBusObjectPathVTable vtable = { - /* .unregister_function = */ unregister_vtable, - /* .message_function = */ message_received, -}; static void handle_dbus_err(bool error_flag, DBusError *err) { @@ -630,23 +504,6 @@ static void handle_dbus_err(bool error_flag, DBusError *err) CC_DBUS_NAME); } -/* - * Initialization works as follows: - * - * we call dbus_bus_get - * we call dbus_connection_set_watch_functions - * libdbus calls back add_watch(watch:0x2341090, data), this watch is for writing - * we call toggled_watch, but it finds that watch is not to be enabled yet - * libdbus calls back add_watch(watch:0x23410e0, data), this watch is for reading - * we call toggled_watch, it adds watch's fd to glib main loop with POLLIN - * (note: these watches are different objects, but they have the same fd) - * we call dbus_connection_set_timeout_functions - * we call dbus_connection_register_object_path - * we call dbus_bus_request_name - * libdbus calls back add_timeout() - * libdbus calls back remove_timeout() - * (therefore there is no code yet in timeout_toggled (see above), it's not used) - */ CCommLayerServerDBus::CCommLayerServerDBus() { DBusConnection* conn; @@ -657,44 +514,8 @@ CCommLayerServerDBus::CCommLayerServerDBus() g_dbus_conn = conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); handle_dbus_err(conn == NULL, &err); -//do we need this? why? -//log("dbus_connection_set_dispatch_status_function"); -// dbus_connection_set_dispatch_status_function(conn, -// dispatch, /* void dispatch(DBusConnection *conn, DBusDispatchStatus new_status, void* data) */ -// NULL, /* data */ -// NULL /* free_data_function */ -// ) - VERB3 log("dbus_connection_set_watch_functions"); - if (!dbus_connection_set_watch_functions(conn, - add_watch, - remove_watch, - toggled_watch, - NULL, /* data */ - NULL /* free_data_function */ - ) - ) { - die_out_of_memory(); - } - VERB3 log("dbus_connection_set_timeout_functions"); - if (!dbus_connection_set_timeout_functions(conn, - add_timeout, - remove_timeout, - timeout_toggled, - NULL, /* data */ - NULL /* free_data_function */ - ) - ) { - die_out_of_memory(); - } - VERB3 log("dbus_connection_register_object_path"); - if (!dbus_connection_register_object_path(conn, - "/com/redhat/abrt", - &vtable, - NULL /* data */ - ) - ) { - die_out_of_memory(); - } + attach_dbus_conn_to_glib_main_loop(conn, "/com/redhat/abrt", message_received); + VERB3 log("dbus_bus_request_name"); int rc = dbus_bus_request_name(conn, CC_DBUS_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err); handle_dbus_err(rc < 0, &err); diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp index 5a5dfeb2..780210cb 100644 --- a/src/Daemon/Daemon.cpp +++ b/src/Daemon/Daemon.cpp @@ -112,7 +112,6 @@ typedef struct cron_callback_data_t static uint8_t s_sig_caught; static GMainLoop* g_pMainloop; -int g_verbose; CCommLayerServer* g_pCommLayer; pthread_mutex_t g_pJobsMutex; diff --git a/src/Daemon/Daemon.h b/src/Daemon/Daemon.h index e03d983a..c9a653ac 100644 --- a/src/Daemon/Daemon.h +++ b/src/Daemon/Daemon.h @@ -28,16 +28,6 @@ class CCrashWatcher; class CCommLayerServer; class CPluginManager; -/* Verbosity level */ -extern int g_verbose; -/* VERB1 log("what you sometimes want to see, even on a production box") */ -#define VERB1 if (g_verbose >= 1) -/* VERB2 log("debug message, not going into insanely small details") */ -#define VERB2 if (g_verbose >= 2) -/* VERB3 log("lots and lots of details") */ -#define VERB3 if (g_verbose >= 3) -/* there is no level > 3 */ - /* Used for sending dbus signals */ extern CCommLayerServer *g_pCommLayer; |