diff options
author | why <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-06-05 05:40:03 +0000 |
---|---|---|
committer | why <why@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2003-06-05 05:40:03 +0000 |
commit | bd368e97495ba28ea56da862cd8ef0d695572604 (patch) | |
tree | becf1f2e18563680a51e0de4293a13179b889ff4 /ext | |
parent | 017d4ff10ae32ed6570b5d33a8106bd1f22e008f (diff) | |
download | ruby-bd368e97495ba28ea56da862cd8ef0d695572604.tar.gz |
* 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.c | 54 | ||||
-rw-r--r-- | ext/syck/syck.h | 2 |
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> |