summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorwhy <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-06-05 05:40:03 +0000
committerwhy <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-06-05 05:40:03 +0000
commitbd368e97495ba28ea56da862cd8ef0d695572604 (patch)
treebecf1f2e18563680a51e0de4293a13179b889ff4 /ext
parent017d4ff10ae32ed6570b5d33a8106bd1f22e008f (diff)
* ext/syck/rubyext.c: using GC nodes caused segfault. [ruby-core:1071]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3906 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/syck/rubyext.c54
-rw-r--r--ext/syck/syck.h2
2 files changed, 41 insertions, 15 deletions
diff --git a/ext/syck/rubyext.c b/ext/syck/rubyext.c
index df4d4703b9..fc83bf5189 100644
--- a/ext/syck/rubyext.c
+++ b/ext/syck/rubyext.c
@@ -33,6 +33,11 @@ SYMID rb_syck_parse_handler _((SyckParser *, SyckNode *));
SYMID rb_syck_load_handler _((SyckParser *, SyckNode *));
void rb_syck_err_handler _((SyckParser *, char *));
+struct parser_xtra {
+ VALUE data; // Borrowed this idea from marshal.c to fix [ruby-dev:8067] problem
+ VALUE proc;
+};
+
/*
* read from io.
*/
@@ -201,6 +206,7 @@ rb_syck_parse_handler(p, n)
{
VALUE t, v, obj;
int i;
+ struct parser_xtra *bonus;
obj = rb_obj_alloc(cNode);
if ( n->type_id != NULL )
@@ -240,12 +246,14 @@ rb_syck_parse_handler(p, n)
break;
}
- if ( p->bonus != 0 )
+ bonus = (struct parser_xtra *)p->bonus;
+ if ( bonus->proc != 0 )
{
- VALUE proc = (VALUE)p->bonus;
- rb_funcall(proc, rb_intern("call"), 1, v);
+ rb_funcall(bonus->proc, rb_intern("call"), 1, v);
}
+
rb_iv_set(obj, "@value", v);
+ rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
return obj;
}
@@ -262,6 +270,7 @@ rb_syck_load_handler(p, n)
long i;
int str = 0;
int check_transfers = 0;
+ struct parser_xtra *bonus;
switch (n->kind)
{
@@ -358,10 +367,10 @@ rb_syck_load_handler(p, n)
break;
}
- if ( p->bonus != 0 )
+ bonus = (struct parser_xtra *)p->bonus;
+ if ( bonus->proc != 0 )
{
- VALUE proc = (VALUE)p->bonus;
- rb_funcall(proc, rb_intern("call"), 1, obj);
+ rb_funcall(bonus->proc, rb_intern("call"), 1, obj);
}
if ( check_transfers == 1 && n->type_id != NULL )
@@ -369,6 +378,7 @@ rb_syck_load_handler(p, n)
obj = rb_funcall( oDefaultLoader, rb_intern( "transfer" ), 2, rb_str_new2( n->type_id ), obj );
}
+ rb_hash_aset(bonus->data, INT2FIX(RHASH(bonus->data)->tbl->num_entries), obj);
return obj;
}
@@ -444,6 +454,12 @@ syck_mark_parser(parser)
{
rb_gc_mark(parser->root);
rb_gc_mark(parser->root_on_error);
+ if ( parser->bonus != 0 )
+ {
+ struct parser_xtra *bonus = (struct parser_xtra *)parser->bonus;
+ rb_gc_mark(bonus->proc);
+ rb_gc_mark(bonus->data);
+ }
}
/*
@@ -494,6 +510,8 @@ syck_parser_load(argc, argv, self)
{
VALUE port, proc, v, model;
SyckParser *parser;
+ struct parser_xtra bonus;
+ volatile VALUE hash; /* protect from GC */
rb_scan_args(argc, argv, "11", &port, &proc);
Data_Get_Struct(self, SyckParser, parser);
@@ -502,12 +520,11 @@ syck_parser_load(argc, argv, self)
model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
syck_set_model( parser, model );
- parser->bonus = 0;
- if ( !NIL_P( proc ) )
- {
- parser->bonus = (void *)proc;
- }
-
+ bonus.data = hash = rb_hash_new();
+ if ( NIL_P( proc ) ) bonus.proc = 0;
+ else bonus.proc = proc;
+
+ parser->bonus = (void *)&bonus;
//v = rb_ensure(rb_run_syck_parse, (VALUE)&parser, rb_syck_ensure, (VALUE)&parser);
@@ -525,6 +542,8 @@ syck_parser_load_documents(argc, argv, self)
{
VALUE port, proc, v, model;
SyckParser *parser;
+ struct parser_xtra bonus;
+ volatile VALUE hash;
rb_scan_args(argc, argv, "1&", &port, &proc);
Data_Get_Struct(self, SyckParser, parser);
@@ -532,15 +551,22 @@ syck_parser_load_documents(argc, argv, self)
model = rb_hash_aref( rb_iv_get( self, "@options" ), sym_model );
syck_set_model( parser, model );
- parser->bonus = 0;
-
+
while ( 1 )
{
+ /* Reset hash for tracking nodes */
+ bonus.data = hash = rb_hash_new();
+ bonus.proc = 0;
+ parser->bonus = (void *)&bonus;
+
+ /* Parse a document */
v = syck_parse( parser );
if ( parser->eof == 1 )
{
break;
}
+
+ /* Pass document to block */
rb_funcall( proc, rb_intern("call"), 1, v );
}
diff --git a/ext/syck/syck.h b/ext/syck/syck.h
index e74b4338ca..2236810816 100644
--- a/ext/syck/syck.h
+++ b/ext/syck/syck.h
@@ -10,7 +10,7 @@
#ifndef SYCK_H
#define SYCK_H
-#define SYCK_VERSION "0.32"
+#define SYCK_VERSION "0.34"
#define YAML_DOMAIN "yaml.org,2002"
#include <stdio.h>