Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ext/stack_frames/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,22 @@ static VALUE buffer_find(VALUE self) {
return Qnil;
}

static void raise_frame_reference_error()
{
rb_raise(rb_eRuntimeError, "Stack frame is no longer valid, its buffer was re-used for another capture");
}

VALUE stack_buffer_profile_frame(VALUE buffer_obj, int index) {
buffer_t *buffer;
TypedData_Get_Struct(buffer_obj, buffer_t, &buffer_data_type, buffer);
if (index >= buffer->length) raise_frame_reference_error();
return buffer->profile_frames[index];
}

int stack_buffer_frame_lineno(VALUE buffer_obj, int index) {
buffer_t *buffer;
TypedData_Get_Struct(buffer_obj, buffer_t, &buffer_data_type, buffer);
if (index >= buffer->length) raise_frame_reference_error();
return buffer->lines[index];
}

Expand Down
2 changes: 1 addition & 1 deletion ext/stack_frames/extconf.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
require 'mkmf'
$CFLAGS << ' -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers'
$CFLAGS << ' -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wno-missing-noreturn'
$CFLAGS << ' -Werror' if ENV['STACK_FRAMES_DEV']
create_makefile("stack_frames/stack_frames")
14 changes: 14 additions & 0 deletions test/stack_frames/buffer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ def test_gc_stress
GC.stress = false
end

def test_frame_invalidated_from_recapture
buffer = StackFrames::Buffer.new(100)
frame1 do
buffer.capture
end
last_index = buffer.length - 1
frame = buffer[last_index]
buffer.capture
exc = assert_raises(RuntimeError) { frame.method_name }
assert_match(/\AStack frame is no longer valid,/, exc.message)
exc2 = assert_raises(RuntimeError) { frame.lineno }
assert_equal(exc.message, exc2.message)
end

private

def skipping_c_frames?
Expand Down