Merge lp:~dshea/timezonemap/location-cycle into lp:timezonemap

Proposed by David Shea
Status: Merged
Merged at revision: 51
Proposed branch: lp:~dshea/timezonemap/location-cycle
Merge into: lp:timezonemap
Diff against target: 76 lines (+35/-7)
1 file modified
src/cc-timezone-map.c (+35/-7)
To merge this branch: bzr merge lp:~dshea/timezonemap/location-cycle
Reviewer Review Type Date Requested Status
Iain Lane Approve
Review via email: mp+254831@code.launchpad.net

Description of the change

An anaconda user noticed (https://bugzilla.redhat.com/show_bug.cgi?id=1190265) that if you repeatedly click the same spot on the map, it will choose different locations for each click (which is intentional), to the point where clicks will start jumping wildly across the map as the search area expands outwards (which is probably less intentional). While looking into this, I found that the handling of the repeated clicks resulted in a memory leak in priv->distances, and if you managed to get to the end of the list it would crash. The first patch addresses the memory problems, and the second limits the location search to a 50px radius.

To post a comment you must log in.
Revision history for this message
Adam Williamson (awilliamson) wrote :

Aw, no is_canada() ? :P

Revision history for this message
Iain Lane (laney) wrote :

Cool, thanks

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/cc-timezone-map.c'
2--- src/cc-timezone-map.c 2013-12-16 17:27:20 +0000
3+++ src/cc-timezone-map.c 2015-03-31 20:04:30 +0000
4@@ -68,6 +68,8 @@
5 CcTimezoneLocation *location;
6 GHashTable *alias_db;
7 GList *distances;
8+ /* Store the head of the list separately so it can be freed later */
9+ GList *distances_head;
10
11 gint previous_x;
12 gint previous_y;
13@@ -594,9 +596,10 @@
14 g_hash_table_destroy (priv->alias_db);
15 priv->alias_db = NULL;
16 }
17- if (priv->distances)
18+ if (priv->distances_head)
19 {
20- g_list_free (priv->distances);
21+ g_list_free (priv->distances_head);
22+ priv->distances_head = NULL;
23 priv->distances = NULL;
24 }
25
26@@ -991,10 +994,15 @@
27 if (x == priv->previous_x && y == priv->previous_y)
28 {
29 priv->distances = g_list_next (priv->distances);
30+ if (!priv->distances)
31+ priv->distances = priv->distances_head;
32+
33 location = (CcTimezoneLocation*) priv->distances->data;
34 } else {
35- g_list_free (priv->distances);
36- priv->distances = NULL;
37+ GList *node;
38+
39+ g_list_free (priv->distances_head);
40+ priv->distances_head = NULL;
41 for (i = 0; i < array->len; i++)
42 {
43 gdouble pointx, pointy, dx, dy;
44@@ -1007,9 +1015,29 @@
45 dy = pointy - y;
46
47 cc_timezone_location_set_dist(loc, (gdouble) dx * dx + dy * dy);
48- priv->distances = g_list_prepend (priv->distances, loc);
49- }
50- priv->distances = g_list_sort (priv->distances, (GCompareFunc) sort_locations);
51+ priv->distances_head = g_list_prepend (priv->distances_head, loc);
52+ }
53+ priv->distances_head = g_list_sort (priv->distances_head, (GCompareFunc) sort_locations);
54+
55+ /* Remove locations from the list with a distance of greater than 50px,
56+ * so that repeated clicks cycle through a smaller area instead of
57+ * jumping all over the map. Start with the second element to ensure
58+ * that at least one element stays in the list.
59+ */
60+ node = priv->distances_head->next;
61+ while (node != NULL)
62+ {
63+ if (cc_timezone_location_get_dist(node->data) > (50 * 50))
64+ {
65+ /* Cut the list off here */
66+ node->prev->next = NULL;
67+ g_list_free(node);
68+ }
69+
70+ node = g_list_next(node);
71+ }
72+
73+ priv->distances = priv->distances_head;
74 location = (CcTimezoneLocation*) priv->distances->data;
75 priv->previous_x = x;
76 priv->previous_y = y;

Subscribers

People subscribed via source and target branches

to all changes: