applet: fix notifications at startup

This commit is contained in:
Jakub Filak 2015-03-20 06:51:21 +01:00
parent f986ffa0b7
commit bc96715ec7
4 changed files with 408 additions and 2 deletions

View File

@ -0,0 +1,26 @@
From e45d05fa7072e52362981cef02fa8429365e14af Mon Sep 17 00:00:00 2001
From: Matej Habrnal <mhabrnal@redhat.com>
Date: Thu, 19 Mar 2015 17:15:31 +0100
Subject: [PATCH] doc: D-Bus api: make desc of DeleteProblem clearer
Signed-off-by: Matej Habrnal <mhabrnal@redhat.com>
---
doc/problems-service/org.freedesktop.Problems.xml.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/problems-service/org.freedesktop.Problems.xml.in b/doc/problems-service/org.freedesktop.Problems.xml.in
index 6fcd990..38ee5b6 100644
--- a/doc/problems-service/org.freedesktop.Problems.xml.in
+++ b/doc/problems-service/org.freedesktop.Problems.xml.in
@@ -274,7 +274,7 @@ for prblmid in problems.GetProblems():
</method>
<method name='DeleteProblem'>
- <tp:docstring>Deletes a specified problem.</tp:docstring>
+ <tp:docstring>Deletes specified problems. The problems are specified as array of problem_dir.</tp:docstring>
<arg type='as' name='problem_dir' direction='in'>
<tp:docstring>An identifier of problem to be deleted.</tp:docstring>
--
2.3.2

View File

@ -0,0 +1,293 @@
From 57895ccd0c6289faada8e5f3327e276ffded46b5 Mon Sep 17 00:00:00 2001
From: Jakub Filak <jfilak@redhat.com>
Date: Thu, 19 Mar 2015 08:35:38 +0100
Subject: [PATCH] applet: get the list of problems through D-Bus service
The default dump location directory is not iterable for regular users.
v2:
problem_create_app_from_env() will return NULL if envp is NULL, so there
is no need to check pi->envp to NULL.
V3:
unref g_problems_proxy
Signed-off-by: Jakub Filak <jfilak@redhat.com>
---
src/applet/applet.c | 143 +++++++++++++++++++++++++++++++++-------------------
1 file changed, 92 insertions(+), 51 deletions(-)
diff --git a/src/applet/applet.c b/src/applet/applet.c
index d6d581a..b471dbc 100644
--- a/src/applet/applet.c
+++ b/src/applet/applet.c
@@ -36,6 +36,14 @@
#include "libabrt.h"
#include "problem_api.h"
+/* 5s timeout*/
+#define ORG_FREEDESKTOP_PROBLEMS_CALL_DEFAULT_TIMEOUT 5000
+
+#define ORG_FREEDESKTOP_PROBLEMS_BUS "org.freedesktop.problems"
+#define ORG_FREEDESKTOP_PROBLEMS_OBJECT "/org/freedesktop/problems"
+#define ORG_FREEDESKTOP_PROBLEMS_INTERFACE "org.freedesktop.problems"
+#define ORG_FREEDESKTOP_PROBLEMS_NAMESPACE(member) "org.freedesktop.problems."member
+
/* libnotify action keys */
#define A_REPORT_REPORT "REPORT"
#define A_RESTART_APPLICATION "RESTART"
@@ -44,8 +52,8 @@
#define NOTIFICATION_ICON_NAME "face-sad-symbolic"
+static GDBusProxy *g_problems_proxy;
static GNetworkMonitor *netmon;
-static char **s_dirs;
static GList *g_deferred_crash_queue;
static guint g_deferred_timeout;
static bool g_gnome_abrt_available;
@@ -110,7 +118,6 @@ typedef struct problem_info {
bool foreign;
guint count;
bool is_packaged;
- char *command_line;
char **envp;
pid_t pid;
bool known;
@@ -129,6 +136,11 @@ static const char *problem_info_get_dir(problem_info_t *pi)
return problem_data_get_content_or_NULL(pi->problem_data, CD_DUMPDIR);
}
+static const char *problem_info_get_command_line(problem_info_t *pi)
+{
+ return problem_data_get_content_or_NULL(pi->problem_data, FILENAME_CMDLINE);
+}
+
static void problem_info_set_dir(problem_info_t *pi, const char *dir)
{
problem_data_add_text_noteditable(pi->problem_data, CD_DUMPDIR, dir);
@@ -186,7 +198,6 @@ static void problem_info_unref(gpointer data)
return;
problem_data_free(pi->problem_data);
- g_free(pi->command_line);
if (pi->envp)
g_strfreev(pi->envp);
g_free(pi);
@@ -200,6 +211,57 @@ static problem_info_t* problem_info_ref(problem_info_t *pi)
return pi;
}
+static GVariant *dbus_call_sync(GDBusProxy *proxy, const gchar *method, GVariant *args)
+{
+ GError *error = NULL;
+ GVariant *const resp = g_dbus_proxy_call_sync(proxy,
+ method,
+ args,
+ G_DBUS_PROXY_FLAGS_NONE,
+ ORG_FREEDESKTOP_PROBLEMS_CALL_DEFAULT_TIMEOUT,
+ /* GCancellable */ NULL,
+ &error);
+ if (error)
+ {
+ error_msg(_("Can't call method '%s' over DBus on path '%s' interface '%s': %s"),
+ method,
+ g_dbus_proxy_get_object_path(proxy),
+ g_dbus_proxy_get_interface_name(proxy),
+ error->message);
+ g_error_free(error);
+ /* resp is NULL in this case */
+ }
+
+
+ return resp;
+}
+
+static int ofd_problems_get_problems(GList **problems)
+{
+ /* GetProblems ( IN , OUT as) */
+ GVariant *dbus_res = dbus_call_sync(g_problems_proxy, "GetProblems", NULL);
+
+ if (dbus_res == NULL)
+ return -1;
+
+ GVariant *resp = g_variant_get_child_value(dbus_res, 0);
+ g_variant_unref(dbus_res);
+
+ const gsize n_results = g_variant_n_children(resp);
+ for (gsize child = 0; child < n_results; ++child)
+ {
+ GVariant *const problem_id = g_variant_get_child_value(resp, child);
+
+ *problems = g_list_prepend(*problems, g_variant_dup_string(problem_id, NULL));
+
+ g_variant_unref(problem_id);
+ }
+
+ g_variant_unref(resp);
+
+ return 0;
+}
+
static void run_event_async(problem_info_t *pi, const char *event_name);
struct event_processing_state
@@ -230,29 +292,6 @@ static void free_event_processing_state(struct event_processing_state *p)
g_free(p);
}
-static GList *add_dirs_to_dirlist(GList *dirlist, const char *dirname)
-{
- DIR *dir = opendir(dirname);
- if (!dir)
- return dirlist;
-
- struct dirent *dent;
- while ((dent = readdir(dir)) != NULL)
- {
- if (dot_or_dotdot(dent->d_name))
- continue;
- char *full_name = concat_path_file(dirname, dent->d_name);
- struct stat statbuf;
- if (lstat(full_name, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
- dirlist = g_list_prepend(dirlist, full_name);
- else
- free(full_name);
- }
- closedir(dir);
-
- return g_list_reverse(dirlist);
-}
-
/* Compares the problem directories to list saved in
* $XDG_CACHE_HOME/abrt/applet_dirlist and updates the applet_dirlist
* with updated list.
@@ -263,12 +302,10 @@ static GList *add_dirs_to_dirlist(GList *dirlist, const char *dirname)
static void new_dir_exists(GList **new_dirs)
{
GList *dirlist = NULL;
- char **pp = s_dirs;
- while (*pp)
+ if (ofd_problems_get_problems(&dirlist) != 0)
{
- log_notice("Looking for crashes in %s", *pp);
- dirlist = add_dirs_to_dirlist(dirlist, *pp);
- pp++;
+ error_msg(_("Failed to get the problem list from Problems D-Bus service."));
+ return;
}
const char *cachedir = g_get_user_cache_dir();
@@ -484,7 +521,7 @@ static void action_restart(NotifyNotification *notification, gchar *action, gpoi
}
problem_info_t *pi = (problem_info_t *)user_data;
- app = problem_create_app_from_cmdline (pi->command_line);
+ app = problem_create_app_from_cmdline (problem_info_get_command_line(pi));
g_assert (app);
if (!g_app_info_launch(G_APP_INFO(app), NULL, NULL, &err))
@@ -575,8 +612,9 @@ static void notify_problem_list(GList *problems)
}
app = problem_create_app_from_env ((const char **)pi->envp, pi->pid);
+
if (!app)
- app = problem_create_app_from_cmdline (pi->command_line);
+ app = problem_create_app_from_cmdline (problem_info_get_command_line(pi));
/* For each problem we'll need to know:
* - Whether or not the crash happened in an “app”
@@ -653,7 +691,7 @@ static void notify_problem_list(GList *problems)
}
else
{
- char *binary = problem_get_argv0 (pi->command_line);
+ char *binary = problem_get_argv0 (problem_info_get_command_line(pi));
notify_body = g_strdup_printf (_("We're sorry, it looks like %s crashed. Please contact the developer if you want to report the issue."),
binary);
g_free (binary);
@@ -950,10 +988,11 @@ static void Crash(GVariant *parameters)
problem_data_add_text_noteditable(pi->problem_data, FILENAME_DUPHASH, duphash);
if (package_name != NULL && package_name[0] != '\0')
problem_data_add_text_noteditable(pi->problem_data, FILENAME_COMPONENT, package_name);
+ if (command_line != NULL)
+ problem_data_add_text_noteditable(pi->problem_data, FILENAME_CMDLINE, command_line);
pi->foreign = foreign_problem;
pi->count = count;
pi->is_packaged = (package_name != NULL);
- pi->command_line = g_strdup(command_line);
pi->envp = (env != NULL) ? g_strsplit (env, "\n", -1) : NULL;
pi->pid = (pid != NULL) ? atoi (pid) : -1;
free(command_line);
@@ -1017,7 +1056,7 @@ name_acquired_handler (GDBusConnection *connection,
if (!dd_exist(dd, FILENAME_REPORTED_TO))
{
problem_info_t *pi = problem_info_new(new_dirs->data);
- const char *elements[] = {FILENAME_UUID, FILENAME_DUPHASH, FILENAME_COMPONENT, FILENAME_NOT_REPORTABLE};
+ const char *elements[] = {FILENAME_UUID, FILENAME_DUPHASH, FILENAME_COMPONENT, FILENAME_NOT_REPORTABLE, FILENAME_CMDLINE};
for (size_t i = 0; i < sizeof(elements)/sizeof(*elements); ++i)
{
@@ -1125,19 +1164,6 @@ int main(int argc, char** argv)
load_event_config_data();
load_user_settings("abrt-applet");
- const char *default_dirs[] = {
- g_settings_dump_location,
- NULL,
- NULL,
- };
- argv += optind;
- if (!argv[0])
- {
- default_dirs[1] = concat_path_file(g_get_user_cache_dir(), "abrt/spool");
- argv = (char**)default_dirs;
- }
- s_dirs = argv;
-
/* Initialize our (dbus_abrt) machinery by filtering
* for signals:
* signal sender=:1.73 -> path=/org/freedesktop/problems; interface=org.freedesktop.problems; member=Crash
@@ -1151,14 +1177,27 @@ int main(int argc, char** argv)
perror_msg_and_die("Can't connect to system dbus: %s", error->message);
guint filter_id = g_dbus_connection_signal_subscribe(system_conn,
NULL,
- "org.freedesktop.problems",
+ ORG_FREEDESKTOP_PROBLEMS_BUS,
"Crash",
- "/org/freedesktop/problems",
+ ORG_FREEDESKTOP_PROBLEMS_OBJECT,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
handle_message,
NULL, NULL);
+ g_problems_proxy = g_dbus_proxy_new_sync(system_conn,
+ G_DBUS_PROXY_FLAGS_NONE,
+ /* GDBusInterfaceInfo */ NULL,
+ ORG_FREEDESKTOP_PROBLEMS_BUS,
+ ORG_FREEDESKTOP_PROBLEMS_OBJECT,
+ ORG_FREEDESKTOP_PROBLEMS_INTERFACE,
+ /* GCancellable */ NULL,
+ &error);
+ if (g_problems_proxy == NULL)
+ perror_msg_and_die(_("Can't connect ot DBus bus '"ORG_FREEDESKTOP_PROBLEMS_BUS \
+ "' path '"ORG_FREEDESKTOP_PROBLEMS_OBJECT \
+ "' interface '"ORG_FREEDESKTOP_PROBLEMS_INTERFACE"': %s"), error->message);
+
guint name_own_id = g_bus_own_name (G_BUS_TYPE_SESSION,
ABRT_DBUS_NAME".applet",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE,
@@ -1198,6 +1237,8 @@ int main(int argc, char** argv)
*/
new_dir_exists(/* new dirs list */ NULL);
+ g_object_unref(g_problems_proxy);
+
if (notify_is_initted())
notify_uninit();
--
2.3.2

View File

@ -0,0 +1,81 @@
From 25a3f7f6f61e387d903e4e1547ad91184131dd8e Mon Sep 17 00:00:00 2001
From: Jakub Filak <jfilak@redhat.com>
Date: Thu, 19 Mar 2015 13:58:16 +0100
Subject: [PATCH] applet: fix freeing of the notify problem list
The functions that process the list also frees the list.
Signed-off-by: Jakub Filak <jfilak@redhat.com>
---
src/applet/applet.c | 24 ++++++++++++++++--------
1 file changed, 16 insertions(+), 8 deletions(-)
diff --git a/src/applet/applet.c b/src/applet/applet.c
index b471dbc..0cf9b49 100644
--- a/src/applet/applet.c
+++ b/src/applet/applet.c
@@ -87,11 +87,17 @@ static bool is_networking_enabled(void)
static void show_problem_list_notification(GList *problems);
static void problem_info_unref(gpointer data);
-static gboolean process_deferred_queue_timeout_fn(GList *queue)
+static gboolean process_deferred_queue_timeout_fn(void)
{
g_deferred_timeout = 0;
- show_problem_list_notification(queue);
- g_list_free_full (queue, problem_info_unref);
+
+ GList *tmp = g_deferred_crash_queue;
+ g_deferred_crash_queue = NULL;
+
+ /* this function calls push_to_deferred_queue() which appends data to
+ * g_deferred_crash_queue but the function also modifies the argument
+ * so we must reset g_deferred_crash_queue before the call */
+ show_problem_list_notification(tmp);
/* Remove this timeout fn from the main loop*/
return G_SOURCE_REMOVE;
@@ -107,8 +113,7 @@ static void connectivity_changed_cb(GObject *gobject,
if (g_deferred_timeout)
g_source_remove(g_deferred_timeout);
- g_deferred_timeout = g_idle_add ((GSourceFunc)process_deferred_queue_timeout_fn,
- g_deferred_crash_queue);
+ g_deferred_timeout = g_idle_add ((GSourceFunc)process_deferred_queue_timeout_fn, NULL);
}
}
@@ -583,6 +588,9 @@ add_restart_app_button (NotifyNotification *notification,
problem_info_ref (pi), problem_info_unref);
}
+/*
+ * Destroys the problems argument
+ */
static void notify_problem_list(GList *problems)
{
if (problems == NULL)
@@ -890,6 +898,9 @@ static void run_event_async(problem_info_t *pi, const char *event_name)
handle_event_output_cb, state);
}
+/*
+ * Destroys the problems argument
+ */
static void show_problem_list_notification(GList *problems)
{
if (is_autoreporting_enabled())
@@ -1086,10 +1097,7 @@ next:
}
if (notify_list)
- {
show_problem_list_notification(notify_list);
- g_list_free_full (notify_list, problem_info_unref);
- }
list_free_with_free(new_dirs);
--
2.3.2

View File

@ -46,7 +46,7 @@
Summary: Automatic bug detection and reporting tool
Name: abrt
Version: 2.5.0
Release: 1%{?dist}
Release: 2%{?dist}
License: GPLv2+
Group: Applications/System
URL: https://github.com/abrt/abrt/wiki/ABRT-Project
@ -55,7 +55,10 @@ Source: https://fedorahosted.org/released/%{name}/%{name}-%{version}.tar.gz
Patch0: disable-OpenGPGCheck-in-Fedora-Rawhide.patch
# git format-patch %%{Version} --topo-order -N -M;
# for p in `ls 0*.patch`; do printf "Patch%04d: %s\n" $i $p; ((i++)); done
# i=1; for p in `ls 0*.patch`; do printf "Patch%04d: %s\n" $i $p; ((i++)); done
Patch0001: 0001-doc-D-Bus-api-make-desc-of-DeleteProblem-clearer.patch
Patch0002: 0002-applet-get-the-list-of-problems-through-D-Bus-servic.patch
Patch0003: 0003-applet-fix-freeing-of-the-notify-problem-list.patch
# '%%autosetup -S git' -> git
BuildRequires: git
@ -1024,6 +1027,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%config(noreplace) %{_sysconfdir}/profile.d/abrt-console-notification.sh
%changelog
* Fri Mar 20 2015 Jakub Filak <jfilak@redhat.com> 2.5.0-2
- applet: re-enable notifications of problems not-yet seen problems at start-up
* Wed Mar 18 2015 Jakub Filak <jfilak@redhat.com> 2.5.0-1
- dbus: add a new method GetProblemData
- abrt_event: run save package data event even if component exists