Merge lp:~ken-vandine/gwibber/lp_959068 into lp:gwibber

Proposed by Ken VanDine
Status: Merged
Merged at revision: 1333
Proposed branch: lp:~ken-vandine/gwibber/lp_959068
Merge into: lp:gwibber
Diff against target: 26 lines (+9/-1)
1 file modified
libgwibber/streams.vala (+9/-1)
To merge this branch: bzr merge lp:~ken-vandine/gwibber/lp_959068
Reviewer Review Type Date Requested Status
Michael Terry (community) Approve
Review via email: mp+100874@code.launchpad.net

This proposal supersedes a proposal from 2012-04-04.

Description of the change

Defer calling unset on the seen HashMap until after we are done iterating it,
it will resize making the iterator invalid. (LP: #959068)

This is fixed in the 0.7 series of libgee https://bugzilla.gnome.org/show_bug.cgi?id=671327

To post a comment you must log in.
Revision history for this message
Michael Terry (mterry) wrote : Posted in a previous version of this proposal

As discussed on IRC, the change seems harmless. Might warrant a comment in code, because otherwise that coding pattern is odd and liable to be removed accidentally in future.

review: Approve
Revision history for this message
Ken VanDine (ken-vandine) wrote :

Two test cases, the first one crashes the second one doesn't. Should validate the work around.

/*
 * build with:
 * valac --pkg gee-1.0 gee-test1.vala -o gee-test1
 */

static int main(string[] args)
{
  var map = new Gee.HashMap <string, string?> ();
  map["one"] = "one";
  map["two"] = "two";
  map["three"] = "three";
  map["four"] = "four";

  print ("map size is %d\n", map.size);

  foreach (var v in map.entries)
  {
    print ("Found %s\n", v.value);
    map.unset(v.key);
  }

  print ("map size is %d\n", map.size);

  return 0;
}
ken@trabajo:~/src/gwibber/lp_959068$ cat examples/gee-test2.vala
/*
 * build with:
 * valac --pkg gee-1.0 gee-test2.vala -o gee-test2
 */

static int main(string[] args)
{
  var map = new Gee.HashMap <string, string?> ();
  map["one"] = "one";
  map["two"] = "two";
  map["three"] = "three";
  map["four"] = "four";

  print ("map size is %d\n", map.size);

  var to_remove = new GLib.List <string> ();

  foreach (var v in map.entries)
  {
    print ("Found %s\n", v.value);
    to_remove.append (v.key);
  }
  foreach (var v in to_remove)
    map.unset(v);

  print ("map size is %d\n", map.size);

  return 0;
}

Revision history for this message
Michael Terry (mterry) wrote :

Ah, that makes sense! Since order doesn't matter here, you might want to use prepend instead of append (better performance), but no big deal.

review: Approve
Revision history for this message
Ken VanDine (ken-vandine) wrote :

great, will do!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'libgwibber/streams.vala'
2--- libgwibber/streams.vala 2012-03-19 13:35:30 +0000
3+++ libgwibber/streams.vala 2012-04-04 20:31:26 +0000
4@@ -213,13 +213,21 @@
5 model = create_model ();
6 }
7 model.row_removed.connect((_m, _i) => {
8+ var to_remove = new GLib.List <string> ();
9 foreach (var v in seen.entries)
10 {
11 if (v.value == _i)
12 {
13- seen.unset(v.key);
14+ /* defer calling unset until after we are done iterating
15+ * the HashMap, it will resize making the iterator invalid
16+ * This is fixed in the 0.7 series of libgee
17+ * https://bugzilla.gnome.org/show_bug.cgi?id=671327
18+ */
19+ to_remove.append (v.key);
20 }
21 }
22+ foreach (var v in to_remove)
23+ seen.unset(v);
24 });
25 Idle.add(() => {
26 refresh_model_async.begin ();