diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-05-13 19:42:27 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-05-13 19:42:27 -0700 |
commit | 4943963188ffb39f301a7e7ce073d9673b507a87 (patch) | |
tree | 6ddef38e3dfa8cca28240b7ea505277db57ced15 | |
parent | ebdd69bedb00e158ff9ea940cd4c661c53cfec12 (diff) | |
download | txr-4943963188ffb39f301a7e7ce073d9673b507a87.tar.gz txr-4943963188ffb39f301a7e7ce073d9673b507a87.tar.bz2 txr-4943963188ffb39f301a7e7ce073d9673b507a87.zip |
bugfix: gc-incorrect creation of catenated stream.
* stream.c (make_catenated_stream): Fix incorrect order
of operations: list of streams stored into a structure
that is not yet visible to the garbage collector.
(Rules for coding this properly are explained in
HACKING.) This was found by running a test with --gc-debug
on 64 bit Darwin. The read_eval_stream function calls
make_catenated_stream with an argument that is freshly
constructed in the argument expression itself, triggering
the issue.
-rw-r--r-- | stream.c | 5 |
1 files changed, 4 insertions, 1 deletions
@@ -2343,9 +2343,12 @@ static struct strm_ops cat_stream_ops = val make_catenated_stream(val stream_list) { struct cat_strm *s = coerce(struct cat_strm *, chk_malloc(sizeof *s)); + val catstrm = nil; strm_base_init(&s->a); + s->streams = nil; + catstrm = cobj(coerce(mem_t *, s), stream_s, &cat_stream_ops.cobj_ops); s->streams = stream_list; - return cobj(coerce(mem_t *, s), stream_s, &cat_stream_ops.cobj_ops); + return catstrm; } val make_catenated_stream_v(struct args *streams) |