Skip to content

Commit edb80df

Browse files
committed
add additional CF info for CI env
Introduce new RUBY_DEBUG option 'ci' to inform Ruby interpreter that an interpreter is running on CI environment. With this option, `rb_bug()` shows more information includes method entry information, local variables information for each control frame.
1 parent c88afd5 commit edb80df

File tree

4 files changed

+50
-12
lines changed

4 files changed

+50
-12
lines changed

debug.c

+2
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ extern int ruby_w32_rtc_error;
147147
UINT ruby_w32_codepage[2];
148148
#endif
149149
extern int ruby_rgengc_debug;
150+
extern int ruby_on_ci;
150151

151152
int
152153
ruby_env_debug_option(const char *str, int len, void *arg)
@@ -192,6 +193,7 @@ ruby_env_debug_option(const char *str, int len, void *arg)
192193

193194
SET_WHEN("gc_stress", *ruby_initial_gc_stress_ptr, Qtrue);
194195
SET_WHEN("core", ruby_enable_coredump, 1);
196+
SET_WHEN("ci", ruby_on_ci, 1);
195197
if (NAME_MATCH_VALUE("rgengc")) {
196198
if (!len) ruby_rgengc_debug = 1;
197199
else SET_UINT_LIST("rgengc", &ruby_rgengc_debug, 1);

gc.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -11344,8 +11344,8 @@ obj_type_name(VALUE obj)
1134411344
return type_name(TYPE(obj), obj);
1134511345
}
1134611346

11347-
static const char *
11348-
method_type_name(rb_method_type_t type)
11347+
const char *
11348+
rb_method_type_name(rb_method_type_t type)
1134911349
{
1135011350
switch (type) {
1135111351
case VM_METHOD_TYPE_ISEQ: return "iseq";
@@ -11361,7 +11361,7 @@ method_type_name(rb_method_type_t type)
1136111361
case VM_METHOD_TYPE_UNDEF: return "undef";
1136211362
case VM_METHOD_TYPE_NOTIMPLEMENTED: return "notimplemented";
1136311363
}
11364-
rb_bug("method_type_name: unreachable (type: %d)", type);
11364+
rb_bug("rb_method_type_name: unreachable (type: %d)", type);
1136511365
}
1136611366

1136711367
/* from array.c */
@@ -11564,7 +11564,7 @@ rb_raw_obj_info(char *buff, const int buff_size, VALUE obj)
1156411564
if (me->def) {
1156511565
APPENDF((BUFF_ARGS, "(called_id: %s, type: %s, alias: %d, owner: %s, defined_class: %s)",
1156611566
rb_id2name(me->called_id),
11567-
method_type_name(me->def->type),
11567+
rb_method_type_name(me->def->type),
1156811568
me->def->alias_count,
1156911569
obj_info(me->owner),
1157011570
obj_info(me->defined_class)));

test/ruby/test_rubyoptions.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ module SEGVTest
674674
%r(
675675
(?:--\s(?:.+\n)*\n)?
676676
--\sControl\sframe\sinformation\s-+\n
677-
(?:c:.*\n)*
677+
(?:(?:c:.*\n)|(?:^\s+.+\n))*
678678
\n
679679
)x,
680680
%r(

vm_dump.c

+43-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#include "addr2line.h"
1414
#include "vm_core.h"
1515
#include "iseq.h"
16+
#include "gc.h"
17+
1618
#ifdef HAVE_UCONTEXT_H
1719
#include <ucontext.h>
1820
#endif
@@ -38,6 +40,9 @@
3840
((rb_control_frame_t *)((ec)->vm_stack + (ec)->vm_stack_size) - \
3941
(rb_control_frame_t *)(cfp))
4042

43+
const char *rb_method_type_name(rb_method_type_t type);
44+
int ruby_on_ci;
45+
4146
static void
4247
control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *cfp)
4348
{
@@ -46,11 +51,10 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
4651
char ep_in_heap = ' ';
4752
char posbuf[MAX_POSBUF+1];
4853
int line = 0;
49-
5054
const char *magic, *iseq_name = "-", *selfstr = "-", *biseq_name = "-";
5155
VALUE tmp;
52-
53-
const rb_callable_method_entry_t *me;
56+
const rb_iseq_t *iseq = NULL;
57+
const rb_callable_method_entry_t *me = rb_vm_frame_method_entry(cfp);
5458

5559
if (ep < 0 || (size_t)ep > ec->vm_stack_size) {
5660
ep = (ptrdiff_t)cfp->ep;
@@ -110,15 +114,16 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
110114
line = -1;
111115
}
112116
else {
113-
pc = cfp->pc - cfp->iseq->body->iseq_encoded;
114-
iseq_name = RSTRING_PTR(cfp->iseq->body->location.label);
117+
iseq = cfp->iseq;
118+
pc = cfp->pc - iseq->body->iseq_encoded;
119+
iseq_name = RSTRING_PTR(iseq->body->location.label);
115120
line = rb_vm_get_sourceline(cfp);
116121
if (line) {
117-
snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(rb_iseq_path(cfp->iseq)), line);
122+
snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(rb_iseq_path(iseq)), line);
118123
}
119124
}
120125
}
121-
else if ((me = rb_vm_frame_method_entry(cfp)) != NULL) {
126+
else if (me != NULL) {
122127
iseq_name = rb_id2name(me->def->original_id);
123128
snprintf(posbuf, MAX_POSBUF, ":%s", iseq_name);
124129
line = -1;
@@ -148,6 +153,37 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
148153
fprintf(stderr, "%-1s ", biseq_name);
149154
}
150155
fprintf(stderr, "\n");
156+
157+
// additional information for CI machines
158+
if (ruby_on_ci) {
159+
char buff[0x100];
160+
161+
if (me) {
162+
if (imemo_type_p((VALUE)me, imemo_ment)) {
163+
fprintf(stderr, " me:\n");
164+
fprintf(stderr, " called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type));
165+
fprintf(stderr, " owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner));
166+
if (me->owner != me->defined_class) {
167+
fprintf(stderr, " defined_class: %s\n", rb_raw_obj_info(buff, 0x100, me->defined_class));
168+
}
169+
}
170+
else {
171+
fprintf(stderr, " me is corrupted (%s)\n", rb_raw_obj_info(buff, 0x100, (VALUE)me));
172+
}
173+
}
174+
175+
if (iseq) {
176+
if (iseq->body->local_table_size > 0) {
177+
fprintf(stderr, " lvars:\n");
178+
for (unsigned int i=0; i<iseq->body->local_table_size; i++) {
179+
const VALUE *argv = cfp->ep - cfp->iseq->body->local_table_size - VM_ENV_DATA_SIZE + 1;
180+
fprintf(stderr, " %s: %s\n",
181+
rb_id2name(iseq->body->local_table[i]),
182+
rb_raw_obj_info(buff, 0x100, argv[i]));
183+
}
184+
}
185+
}
186+
}
151187
}
152188

153189
void

0 commit comments

Comments
 (0)