Skip to content

Commit 4da4878

Browse files
remove: test
1 parent e147516 commit 4da4878

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

test_bug.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Foo
2+
x = 1
3+
10.times do
4+
Proc.new { x }
5+
end
6+
end

vm.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "zjit.h"
4040
#include "ruby/st.h"
4141
#include "ruby/vm.h"
42+
#include "ruby/debug.h"
4243
#include "vm_core.h"
4344
#include "vm_callinfo.h"
4445
#include "vm_debug.h"
@@ -1073,6 +1074,33 @@ vm_block_handler_escape(const rb_execution_context_t *ec, VALUE block_handler)
10731074
return Qnil;
10741075
}
10751076

1077+
/*
1078+
* Simulate rb_profile_frames arriving via signal at an arbitrary point
1079+
* during env escape, to reproduce bugs where a profiler interrupts
1080+
* vm_make_env_each mid-mutation.
1081+
*
1082+
* Gated behind RUBY_DEBUG_PROFILE_DURING_ESCAPE=1 so that miniruby
1083+
* and normal builds are unaffected. Run your reproducer with:
1084+
*
1085+
* RUBY_DEBUG_PROFILE_DURING_ESCAPE=1 ./miniruby bug_example.rb
1086+
*/
1087+
// Simulate rb_profile_frames arriving via signal at an arbitrary point
1088+
// during env escape, to reproduce bugs where a profiler interrupts
1089+
// vm_make_env_each mid-mutation.
1090+
static void
1091+
vm_escape_debug_profile_frames(void)
1092+
{
1093+
static int enabled = -1;
1094+
if (UNLIKELY(enabled == -1)) {
1095+
enabled = (getenv("RUBY_DEBUG_PROFILE_DURING_ESCAPE") != NULL);
1096+
}
1097+
if (LIKELY(!enabled)) return;
1098+
1099+
VALUE debug_buff[128];
1100+
int debug_lines[128];
1101+
rb_profile_frames(0, 128, debug_buff, debug_lines);
1102+
}
1103+
10761104
static VALUE
10771105
vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *const cfp)
10781106
{
@@ -1084,6 +1112,8 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
10841112
return VM_ENV_ENVVAL(ep);
10851113
}
10861114

1115+
vm_escape_debug_profile_frames();
1116+
10871117
if (!VM_ENV_LOCAL_P(ep)) {
10881118
const VALUE *prev_ep = VM_ENV_PREV_EP(ep);
10891119
if (!VM_ENV_ESCAPED_P(prev_ep)) {
@@ -1095,16 +1125,21 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
10951125
}
10961126

10971127
vm_make_env_each(ec, prev_cfp);
1128+
vm_escape_debug_profile_frames();
10981129
VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep));
1130+
vm_escape_debug_profile_frames();
10991131
}
11001132
}
11011133
else {
11021134
VM_ASSERT(VM_ENV_LOCAL_P(ep));
11031135
VALUE block_handler = VM_ENV_BLOCK_HANDLER(ep);
11041136

11051137
if (block_handler != VM_BLOCK_HANDLER_NONE) {
1138+
vm_escape_debug_profile_frames();
11061139
VALUE blockprocval = vm_block_handler_escape(ec, block_handler);
1140+
vm_escape_debug_profile_frames();
11071141
VM_STACK_ENV_WRITE(ep, VM_ENV_DATA_INDEX_SPECVAL, blockprocval);
1142+
vm_escape_debug_profile_frames();
11081143
}
11091144
}
11101145

@@ -1147,7 +1182,9 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
11471182

11481183
// Careful with order in the following sequence. Each allocation can move objects.
11491184
env_body = ALLOC_N(VALUE, env_size);
1185+
vm_escape_debug_profile_frames();
11501186
rb_env_t *env = IMEMO_NEW(rb_env_t, imemo_env, 0);
1187+
vm_escape_debug_profile_frames();
11511188

11521189
// Set up env without WB since it's brand new (similar to newobj_init(), newobj_fill())
11531190
MEMCPY(env_body, ep - (local_size - 1 /* specval */), VALUE, local_size);
@@ -1159,10 +1196,16 @@ vm_make_env_each(const rb_execution_context_t * const ec, rb_control_frame_t *co
11591196
env->ep = env_ep;
11601197
env->env = env_body;
11611198
env->env_size = env_size;
1199+
vm_escape_debug_profile_frames();
11621200

11631201
cfp->ep = env_ep;
1202+
vm_escape_debug_profile_frames();
1203+
11641204
VM_ENV_FLAGS_SET(env_ep, VM_ENV_FLAG_ESCAPED | VM_ENV_FLAG_WB_REQUIRED);
1205+
vm_escape_debug_profile_frames();
1206+
11651207
VM_STACK_ENV_WRITE(ep, 0, (VALUE)env); /* GC mark */
1208+
vm_escape_debug_profile_frames();
11661209

11671210
#if 0
11681211
for (i = 0; i < local_size; i++) {

0 commit comments

Comments
 (0)