From 79f22da9c87d295bd39ea24250c2d64df8110cc9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 20 Sep 2010 18:43:19 -0700 Subject: fix segfault from unpredictable GC ordering We cannot guarantee GC will mark valid nodes when the tree the node belongs to is destroyed, so we have to allocate a new node that is a copy of the original node whenever we create Patricia::Node objects --- ext/rpatricia/rpatricia.c | 9 ++++++--- test/test_old_segfaults.rb | 8 ++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ext/rpatricia/rpatricia.c b/ext/rpatricia/rpatricia.c index 1c81ba1..ae018af 100644 --- a/ext/rpatricia/rpatricia.c +++ b/ext/rpatricia/rpatricia.c @@ -33,10 +33,13 @@ p_node_mark (void *ptr) } static VALUE -wrap_node(patricia_node_t *node) +wrap_node(patricia_node_t *orig) { - /* node will be freed when parent is freed */ - return Data_Wrap_Struct(cNode, p_node_mark, 0, node); + patricia_node_t *node = ALLOC(patricia_node_t); + + memcpy(node, orig, sizeof(patricia_node_t)); + + return Data_Wrap_Struct(cNode, p_node_mark, -1, node); } static prefix_t * diff --git a/test/test_old_segfaults.rb b/test/test_old_segfaults.rb index 5e7ec3e..96f1b43 100644 --- a/test/test_old_segfaults.rb +++ b/test/test_old_segfaults.rb @@ -30,4 +30,12 @@ class TestOldSegfaults < Test::Unit::TestCase t = Patricia.new assert_equal 0, t.num_nodes end + + def test_gc_ordering_segfault + added = [] + 100000.times do + tmp = Patricia.new + added << tmp.add('8.8.8.8') + end + end end -- cgit v1.2.3-24-ge0c7