Merge lp:~charlesk/indicator-session/lp-1256590-j-random-user into lp:indicator-session/14.04

Proposed by Charles Kerr
Status: Merged
Approved by: Ted Gould
Approved revision: 446
Merged at revision: 443
Proposed branch: lp:~charlesk/indicator-session/lp-1256590-j-random-user
Merge into: lp:indicator-session/14.04
Diff against target: 365 lines (+266/-10)
5 files modified
debian/control (+1/-0)
src/CMakeLists.txt (+2/-0)
src/recoverable-problem.c (+167/-0)
src/recoverable-problem.h (+26/-0)
src/service.c (+70/-10)
To merge this branch: bzr merge lp:~charlesk/indicator-session/lp-1256590-j-random-user
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
Review via email: mp+213353@code.launchpad.net

Commit message

Fix the phantom "J Random User" menuitem that shows up under some conditions.

Description of the change

This patch skips creating menuitems for users that don't have a username.

Sometimes org.freedesktop.login1 gives us a user without a username. Multiple users have reported this happens when running "Remmina Remote Desktop Client."

So we pass a NULL label to glib when we create the menuitem, and when the label property is NULL for an x-canonical-type of "indicator.user-menu-item", the default text of "J Random User" is used.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
445. By Charles Kerr

copy recoverable-problem.[ch] from url-dispatcher 0.1+14.04.20140331.1-0ubuntu1

446. By Charles Kerr

if we encounter a user for whom we can't find a name, report it to apport as a recoverable error.

Revision history for this message
Ted Gould (ted) wrote :

+1

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-03-05 20:12:45 +0000
3+++ debian/control 2014-04-02 15:03:28 +0000
4@@ -32,6 +32,7 @@
5 unity-control-center | gnome-control-center,
6 unity-control-center-signon | gnome-control-center-signon
7 Suggests: lightdm,
8+ apport,
9 zenity
10 Description: indicator showing session management, status and user switching
11 This indicator is designed to be placed on the right side of a panel and
12
13=== modified file 'src/CMakeLists.txt'
14--- src/CMakeLists.txt 2013-07-02 02:00:17 +0000
15+++ src/CMakeLists.txt 2014-04-02 15:03:28 +0000
16@@ -5,6 +5,8 @@
17 actions.h
18 guest.c
19 guest.h
20+ recoverable-problem.c
21+ recoverable-problem.h
22 service.c
23 service.h
24 users.c
25
26=== added file 'src/recoverable-problem.c'
27--- src/recoverable-problem.c 1970-01-01 00:00:00 +0000
28+++ src/recoverable-problem.c 2014-04-02 15:03:28 +0000
29@@ -0,0 +1,167 @@
30+/*
31+ * Copyright 2013 Canonical Ltd.
32+ *
33+ * This program is free software: you can redistribute it and/or modify it
34+ * under the terms of the GNU General Public License version 3, as published
35+ * by the Free Software Foundation.
36+ *
37+ * This program is distributed in the hope that it will be useful, but
38+ * WITHOUT ANY WARRANTY; without even the implied warranties of
39+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
40+ * PURPOSE. See the GNU General Public License for more details.
41+ *
42+ * You should have received a copy of the GNU General Public License along
43+ * with this program. If not, see <http://www.gnu.org/licenses/>.
44+ *
45+ * Authors:
46+ * Ted Gould <ted.gould@canonical.com>
47+ */
48+
49+#include "recoverable-problem.h"
50+#include <glib/gstdio.h>
51+#include <string.h>
52+#include <errno.h>
53+
54+/* Helpers to ensure we write nicely */
55+static void
56+write_string (int fd,
57+ const gchar *string)
58+{
59+ int res;
60+ do
61+ res = write (fd, string, strlen (string));
62+ while (G_UNLIKELY (res == -1 && errno == EINTR));
63+}
64+
65+/* Make NULLs fast and fun! */
66+static void
67+write_null (int fd)
68+{
69+ int res;
70+ do
71+ res = write (fd, "", 1);
72+ while (G_UNLIKELY (res == -1 && errno == EINTR));
73+}
74+
75+/* Child watcher */
76+static gboolean
77+apport_child_watch (GPid pid G_GNUC_UNUSED, gint status G_GNUC_UNUSED, gpointer user_data)
78+{
79+ g_main_loop_quit((GMainLoop *)user_data);
80+ return FALSE;
81+}
82+
83+static gboolean
84+apport_child_timeout (gpointer user_data)
85+{
86+ g_warning("Recoverable Error Reporter Timeout");
87+ g_main_loop_quit((GMainLoop *)user_data);
88+ return FALSE;
89+}
90+
91+/* Code to report an error */
92+void
93+report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, gchar * additional_properties[])
94+{
95+ GSpawnFlags flags;
96+ gboolean first;
97+ GError * error = NULL;
98+ gint error_stdin = 0;
99+ GPid pid = 0;
100+ gchar * pid_str = NULL;
101+ gchar ** argv = NULL;
102+ gchar * argv_nopid[2] = {
103+ "/usr/share/apport/recoverable_problem",
104+ NULL
105+ };
106+ gchar * argv_pid[4] = {
107+ "/usr/share/apport/recoverable_problem",
108+ "-p",
109+ NULL, /* put pid_str when allocated here */
110+ NULL
111+ };
112+
113+
114+ argv = (gchar **)argv_nopid;
115+
116+ if (report_pid != 0) {
117+ pid_str = g_strdup_printf("%d", report_pid);
118+ argv_pid[2] = pid_str;
119+ argv = (gchar**)argv_pid;
120+ }
121+
122+ flags = G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL;
123+ if (wait) {
124+ flags |= G_SPAWN_DO_NOT_REAP_CHILD;
125+ }
126+
127+ g_spawn_async_with_pipes(NULL, /* cwd */
128+ argv,
129+ NULL, /* envp */
130+ flags,
131+ NULL, NULL, /* child setup func */
132+ &pid,
133+ &error_stdin,
134+ NULL, /* stdout */
135+ NULL, /* stderr */
136+ &error);
137+
138+ if (error != NULL) {
139+ g_warning("Unable to report a recoverable error: %s", error->message);
140+ g_error_free(error);
141+ }
142+
143+ first = TRUE;
144+
145+ if (error_stdin != 0 && signature != NULL) {
146+ write_string(error_stdin, "DuplicateSignature");
147+ write_null(error_stdin);
148+ write_string(error_stdin, signature);
149+
150+ first = FALSE;
151+ }
152+
153+ if (error_stdin != 0 && additional_properties != NULL) {
154+ gint i;
155+ for (i = 0; additional_properties[i] != NULL; i++) {
156+ if (!first) {
157+ write_null(error_stdin);
158+ } else {
159+ first = FALSE;
160+ }
161+
162+ write_string(error_stdin, additional_properties[i]);
163+ }
164+ }
165+
166+ if (error_stdin != 0) {
167+ close(error_stdin);
168+ }
169+
170+ if (wait && pid != 0) {
171+ GSource * child_source, * timeout_source;
172+ GMainContext * context = g_main_context_new();
173+ GMainLoop * loop = g_main_loop_new(context, FALSE);
174+
175+ child_source = g_child_watch_source_new(pid);
176+ g_source_attach(child_source, context);
177+ g_source_set_callback(child_source, (GSourceFunc)apport_child_watch, loop, NULL);
178+
179+ timeout_source = g_timeout_source_new_seconds(5);
180+ g_source_attach(timeout_source, context);
181+ g_source_set_callback(timeout_source, apport_child_timeout, loop, NULL);
182+
183+ g_main_loop_run(loop);
184+
185+ g_source_destroy(timeout_source);
186+ g_source_destroy(child_source);
187+ g_main_loop_unref(loop);
188+ g_main_context_unref(context);
189+
190+ g_spawn_close_pid(pid);
191+ }
192+
193+ g_free(pid_str);
194+
195+ return;
196+}
197
198=== added file 'src/recoverable-problem.h'
199--- src/recoverable-problem.h 1970-01-01 00:00:00 +0000
200+++ src/recoverable-problem.h 2014-04-02 15:03:28 +0000
201@@ -0,0 +1,26 @@
202+/*
203+ * Copyright 2013 Canonical Ltd.
204+ *
205+ * This program is free software: you can redistribute it and/or modify it
206+ * under the terms of the GNU General Public License version 3, as published
207+ * by the Free Software Foundation.
208+ *
209+ * This program is distributed in the hope that it will be useful, but
210+ * WITHOUT ANY WARRANTY; without even the implied warranties of
211+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
212+ * PURPOSE. See the GNU General Public License for more details.
213+ *
214+ * You should have received a copy of the GNU General Public License along
215+ * with this program. If not, see <http://www.gnu.org/licenses/>.
216+ *
217+ * Authors:
218+ * Ted Gould <ted.gould@canonical.com>
219+ */
220+
221+#include <gio/gio.h>
222+
223+void report_recoverable_problem (const gchar * signature,
224+ GPid report_pid,
225+ gboolean wait,
226+ gchar * additional_properties[]);
227+
228
229=== modified file 'src/service.c'
230--- src/service.c 2014-03-24 10:19:00 +0000
231+++ src/service.c 2014-04-02 15:03:28 +0000
232@@ -21,6 +21,7 @@
233 #include <gio/gio.h>
234
235 #include "backend.h"
236+#include "recoverable-problem.h"
237 #include "service.h"
238
239 #define BUS_NAME "com.canonical.indicator.session"
240@@ -104,6 +105,7 @@
241 GSimpleAction * user_switcher_action;
242 GSimpleAction * guest_switcher_action;
243 GHashTable * users;
244+ GHashTable * reported_users;
245 guint rebuild_id;
246 int rebuild_flags;
247 GDBusConnection * conn;
248@@ -250,15 +252,15 @@
249 static void
250 maybe_add_users (IndicatorSessionService * self)
251 {
252- if (!show_user_list (self))
253- return;
254-
255- GList * uids, * l;
256-
257- uids = indicator_session_users_get_uids (self->priv->backend_users);
258- for (l=uids; l!=NULL; l=l->next)
259- add_user (self, GPOINTER_TO_UINT(l->data));
260- g_list_free (uids);
261+ if (show_user_list (self))
262+ {
263+ GList * uids, * l;
264+
265+ uids = indicator_session_users_get_uids (self->priv->backend_users);
266+ for (l=uids; l!=NULL; l=l->next)
267+ add_user (self, GPOINTER_TO_UINT(l->data));
268+ g_list_free (uids);
269+ }
270 }
271
272
273@@ -488,6 +490,49 @@
274 return serialized_icon;
275 }
276
277+static void
278+report_unusable_user (IndicatorSessionService * self, const IndicatorSessionUser * u)
279+{
280+ const priv_t * const p = self->priv;
281+ gpointer key;
282+
283+ g_return_if_fail(u != NULL);
284+
285+ key = GUINT_TO_POINTER(u->uid);
286+
287+ if (!g_hash_table_contains (p->reported_users, key))
288+ {
289+ gchar * uid_str;
290+ GPtrArray * additional;
291+ const gchar * const error_name = "indicator-session-unknown-user-error";
292+
293+ /* don't spam apport with duplicates */
294+ g_hash_table_add (p->reported_users, key);
295+
296+ uid_str = g_strdup_printf("%u", u->uid);
297+
298+ additional = g_ptr_array_new (); /* null-terminated key/value pair strs */
299+ g_ptr_array_add (additional, "uid");
300+ g_ptr_array_add (additional, uid_str);
301+ g_ptr_array_add (additional, "icon_file");
302+ g_ptr_array_add (additional, u->icon_file ? u->icon_file : "(null)");
303+ g_ptr_array_add (additional, "is_current_user");
304+ g_ptr_array_add (additional, u->is_current_user ? "true" : "false");
305+ g_ptr_array_add (additional, "is_logged_in");
306+ g_ptr_array_add (additional, u->is_logged_in ? "true" : "false");
307+ g_ptr_array_add (additional, "real_name");
308+ g_ptr_array_add (additional, u->real_name ? u->real_name : "(null)");
309+ g_ptr_array_add (additional, "user_name");
310+ g_ptr_array_add (additional, u->user_name ? u->user_name : "(null)");
311+ g_ptr_array_add (additional, NULL); /* null termination */
312+ report_recoverable_problem(error_name, (GPid)0, FALSE, (gchar**)additional->pdata);
313+
314+ /* cleanup */
315+ g_free (uid_str);
316+ g_ptr_array_free (additional, TRUE);
317+ }
318+}
319+
320 static GMenuModel *
321 create_switch_section (IndicatorSessionService * self, int profile)
322 {
323@@ -576,12 +621,23 @@
324 for (i=0; i<users->len; ++i)
325 {
326 const IndicatorSessionUser * u = g_ptr_array_index (users, i);
327+ const char * label;
328 GVariant * serialized_icon;
329
330 if (profile == PROFILE_LOCKSCREEN && u->is_current_user)
331 continue;
332
333- item = g_menu_item_new (get_user_label (u), NULL);
334+ /* Sometimes we get a user without a username? bus hiccup.
335+ I can't reproduce it, but let's not confuse users with
336+ a meaningless menuitem. (see bug #1263228) */
337+ label = get_user_label (u);
338+ if (!label || !*label)
339+ {
340+ report_unusable_user (self, u);
341+ continue;
342+ }
343+
344+ item = g_menu_item_new (label, NULL);
345 g_menu_item_set_action_and_target (item, "indicator.switch-to-user", "s", u->user_name);
346 g_menu_item_set_attribute (item, "x-canonical-type", "s", "indicator.user-menu-item");
347
348@@ -1095,6 +1151,9 @@
349 g_direct_equal,
350 NULL,
351 (GDestroyNotify)indicator_session_user_free);
352+
353+ p->reported_users = g_hash_table_new (g_direct_hash, g_direct_equal);
354+
355 maybe_add_users (self);
356
357 init_gactions (self);
358@@ -1235,6 +1294,7 @@
359 }
360
361 g_clear_pointer (&p->users, g_hash_table_destroy);
362+ g_clear_pointer (&p->reported_users, g_hash_table_destroy);
363 g_clear_object (&p->backend_users);
364 g_clear_object (&p->backend_guest);
365 g_clear_object (&p->backend_actions);

Subscribers

People subscribed via source and target branches