diff options
| author | John Hawthorn <john@hawthorn.email> | 2025-10-02 12:12:26 -0700 |
|---|---|---|
| committer | John Hawthorn <john@hawthorn.email> | 2025-10-02 13:24:00 -0700 |
| commit | 3cd2407045a67838cf2ab949e5164676b6870958 (patch) | |
| tree | e3407f7f1e3675767617b882946f186b2e97875f /io_buffer.c | |
| parent | 7a4f886cc5e7ebf6fece90491cf4a437576d26a6 (diff) | |
Don't call gc_mark from IO::buffer compact
Previously on our mark_and_move we were calling rb_gc_mark, which isn't
safe to call at compaction time.
Co-authored-by: Luke Gruber <luke.gru@gmail.com>
Diffstat (limited to 'io_buffer.c')
| -rw-r--r-- | io_buffer.c | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/io_buffer.c b/io_buffer.c index 96f13c364a..87e392b791 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -273,7 +273,7 @@ io_buffer_free(struct rb_io_buffer *buffer) } static void -rb_io_buffer_type_mark_and_move(void *_buffer) +rb_io_buffer_type_mark(void *_buffer) { struct rb_io_buffer *buffer = _buffer; if (buffer->source != Qnil) { @@ -282,7 +282,21 @@ rb_io_buffer_type_mark_and_move(void *_buffer) // which can be otherwise moved by GC compaction. rb_gc_mark(buffer->source); } else { - rb_gc_mark_and_move(&buffer->source); + rb_gc_mark_movable(buffer->source); + } + } +} + +static void +rb_io_buffer_type_compact(void *_buffer) +{ + struct rb_io_buffer *buffer = _buffer; + if (buffer->source != Qnil) { + if (RB_TYPE_P(buffer->source, T_STRING)) { + // The `source` String has to be pinned, because the `base` may point to the embedded String content, + // which can be otherwise moved by GC compaction. + } else { + buffer->source = rb_gc_location(buffer->source); } } } @@ -311,10 +325,10 @@ rb_io_buffer_type_size(const void *_buffer) static const rb_data_type_t rb_io_buffer_type = { .wrap_struct_name = "IO::Buffer", .function = { - .dmark = rb_io_buffer_type_mark_and_move, + .dmark = rb_io_buffer_type_mark, .dfree = rb_io_buffer_type_free, .dsize = rb_io_buffer_type_size, - .dcompact = rb_io_buffer_type_mark_and_move, + .dcompact = rb_io_buffer_type_compact, }, .data = NULL, .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE, |
