Abort dumping when output failed

This commit is contained in:
Nobuyoshi Nakada 2023-08-04 15:30:36 +09:00
parent ac244938e8
commit 85984a53e8
2 changed files with 159 additions and 110 deletions

View File

@ -1678,13 +1678,13 @@ VALUE rb_proc_alloc(VALUE klass);
VALUE rb_proc_dup(VALUE self); VALUE rb_proc_dup(VALUE self);
/* for debug */ /* for debug */
extern void rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *); extern bool rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
extern void rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *); extern bool rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *);
extern void rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *); extern bool rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *);
#define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp, stderr) #define SDR() rb_vmdebug_stack_dump_raw(GET_EC(), GET_EC()->cfp, stderr)
#define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp), stderr) #define SDR2(cfp) rb_vmdebug_stack_dump_raw(GET_EC(), (cfp), stderr)
void rb_vm_bugreport(const void *, FILE *); bool rb_vm_bugreport(const void *, FILE *);
typedef void (*ruby_sighandler_t)(int); typedef void (*ruby_sighandler_t)(int);
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5)
NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...)); NORETURN(void rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const void *, const char *fmt, ...));

261
vm_dump.c
View File

@ -46,7 +46,10 @@
const char *rb_method_type_name(rb_method_type_t type); const char *rb_method_type_name(rb_method_type_t type);
int ruby_on_ci; int ruby_on_ci;
static void #define kprintf(...) if (fprintf(errout, __VA_ARGS__) < 0) goto error
#define kputs(s) if (fputs(s, errout) < 0) goto error
static bool
control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout) control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
{ {
ptrdiff_t pc = -1; ptrdiff_t pc = -1;
@ -140,30 +143,30 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
line = -1; line = -1;
} }
fprintf(errout, "c:%04"PRIdPTRDIFF" ", kprintf("c:%04"PRIdPTRDIFF" ",
((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp)); ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size) - cfp));
if (pc == -1) { if (pc == -1) {
fprintf(errout, "p:---- "); kprintf("p:---- ");
} }
else { else {
fprintf(errout, "p:%04"PRIdPTRDIFF" ", pc); kprintf("p:%04"PRIdPTRDIFF" ", pc);
} }
fprintf(errout, "s:%04"PRIdPTRDIFF" ", cfp->sp - ec->vm_stack); kprintf("s:%04"PRIdPTRDIFF" ", cfp->sp - ec->vm_stack);
fprintf(errout, ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000); kprintf(ep_in_heap == ' ' ? "e:%06"PRIdPTRDIFF" " : "E:%06"PRIxPTRDIFF" ", ep % 10000);
fprintf(errout, "%-6s", magic); kprintf("%-6s", magic);
if (line) { if (line) {
fprintf(errout, " %s", posbuf); kprintf(" %s", posbuf);
} }
if (VM_FRAME_FINISHED_P(cfp)) { if (VM_FRAME_FINISHED_P(cfp)) {
fprintf(errout, " [FINISH]"); kprintf(" [FINISH]");
} }
if (0) { if (0) {
fprintf(errout, " \t"); kprintf(" \t");
fprintf(errout, "iseq: %-24s ", iseq_name); kprintf("iseq: %-24s ", iseq_name);
fprintf(errout, "self: %-24s ", selfstr); kprintf("self: %-24s ", selfstr);
fprintf(errout, "%-1s ", biseq_name); kprintf("%-1s ", biseq_name);
} }
fprintf(errout, "\n"); kprintf("\n");
// additional information for CI machines // additional information for CI machines
if (ruby_on_ci) { if (ruby_on_ci) {
@ -171,35 +174,38 @@ control_frame_dump(const rb_execution_context_t *ec, const rb_control_frame_t *c
if (me) { if (me) {
if (IMEMO_TYPE_P(me, imemo_ment)) { if (IMEMO_TYPE_P(me, imemo_ment)) {
fprintf(errout, " me:\n"); kprintf(" me:\n");
fprintf(errout, " called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type)); kprintf(" called_id: %s, type: %s\n", rb_id2name(me->called_id), rb_method_type_name(me->def->type));
fprintf(errout, " owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner)); kprintf(" owner class: %s\n", rb_raw_obj_info(buff, 0x100, me->owner));
if (me->owner != me->defined_class) { if (me->owner != me->defined_class) {
fprintf(errout, " defined_class: %s\n", rb_raw_obj_info(buff, 0x100, me->defined_class)); kprintf(" defined_class: %s\n", rb_raw_obj_info(buff, 0x100, me->defined_class));
} }
} }
else { else {
fprintf(errout, " me is corrupted (%s)\n", rb_raw_obj_info(buff, 0x100, (VALUE)me)); kprintf(" me is corrupted (%s)\n", rb_raw_obj_info(buff, 0x100, (VALUE)me));
} }
} }
fprintf(errout, " self: %s\n", rb_raw_obj_info(buff, 0x100, cfp->self)); kprintf(" self: %s\n", rb_raw_obj_info(buff, 0x100, cfp->self));
if (iseq) { if (iseq) {
if (ISEQ_BODY(iseq)->local_table_size > 0) { if (ISEQ_BODY(iseq)->local_table_size > 0) {
fprintf(errout, " lvars:\n"); kprintf(" lvars:\n");
for (unsigned int i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) { for (unsigned int i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) {
const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1; const VALUE *argv = cfp->ep - ISEQ_BODY(cfp->iseq)->local_table_size - VM_ENV_DATA_SIZE + 1;
fprintf(errout, " %s: %s\n", kprintf(" %s: %s\n",
rb_id2name(ISEQ_BODY(iseq)->local_table[i]), rb_id2name(ISEQ_BODY(iseq)->local_table[i]),
rb_raw_obj_info(buff, 0x100, argv[i])); rb_raw_obj_info(buff, 0x100, argv[i]));
} }
} }
} }
} }
return true;
error:
return false;
} }
void bool
rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout) rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
{ {
#if 0 #if 0
@ -207,58 +213,66 @@ rb_vmdebug_stack_dump_raw(const rb_execution_context_t *ec, const rb_control_fra
const VALUE *ep = cfp->ep; const VALUE *ep = cfp->ep;
VALUE *p, *st, *t; VALUE *p, *st, *t;
fprintf(errout, "-- stack frame ------------\n"); kprintf("-- stack frame ------------\n");
for (p = st = ec->vm_stack; p < sp; p++) { for (p = st = ec->vm_stack; p < sp; p++) {
fprintf(errout, "%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p); kprintf("%04ld (%p): %08"PRIxVALUE, (long)(p - st), p, *p);
t = (VALUE *)*p; t = (VALUE *)*p;
if (ec->vm_stack <= t && t < sp) { if (ec->vm_stack <= t && t < sp) {
fprintf(errout, " (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF((VALUE)t) - ec->vm_stack)); kprintf(" (= %ld)", (long)((VALUE *)GC_GUARDED_PTR_REF((VALUE)t) - ec->vm_stack));
} }
if (p == ep) if (p == ep)
fprintf(errout, " <- ep"); kprintf(" <- ep");
fprintf(errout, "\n"); kprintf("\n");
} }
#endif #endif
fprintf(errout, "-- Control frame information " kprintf("-- Control frame information "
"-----------------------------------------------\n"); "-----------------------------------------------\n");
while ((void *)cfp < (void *)(ec->vm_stack + ec->vm_stack_size)) { while ((void *)cfp < (void *)(ec->vm_stack + ec->vm_stack_size)) {
control_frame_dump(ec, cfp, errout); control_frame_dump(ec, cfp, errout);
cfp++; cfp++;
} }
fprintf(errout, "\n"); kprintf("\n");
return true;
error:
return false;
} }
void bool
rb_vmdebug_stack_dump_raw_current(void) rb_vmdebug_stack_dump_raw_current(void)
{ {
const rb_execution_context_t *ec = GET_EC(); const rb_execution_context_t *ec = GET_EC();
rb_vmdebug_stack_dump_raw(ec, ec->cfp, stderr); return rb_vmdebug_stack_dump_raw(ec, ec->cfp, stderr);
} }
void bool
rb_vmdebug_env_dump_raw(const rb_env_t *env, const VALUE *ep, FILE *errout) rb_vmdebug_env_dump_raw(const rb_env_t *env, const VALUE *ep, FILE *errout)
{ {
unsigned int i; unsigned int i;
fprintf(errout, "-- env --------------------\n"); kprintf("-- env --------------------\n");
while (env) { while (env) {
fprintf(errout, "--\n"); kprintf("--\n");
for (i = 0; i < env->env_size; i++) { for (i = 0; i < env->env_size; i++) {
fprintf(errout, "%04d: %08"PRIxVALUE" (%p)", i, env->env[i], (void *)&env->env[i]); kprintf("%04d: %08"PRIxVALUE" (%p)", i, env->env[i], (void *)&env->env[i]);
if (&env->env[i] == ep) fprintf(errout, " <- ep"); if (&env->env[i] == ep) kprintf(" <- ep");
fprintf(errout, "\n"); kprintf("\n");
} }
env = rb_vm_env_prev_env(env); env = rb_vm_env_prev_env(env);
} }
fprintf(errout, "---------------------------\n"); kprintf("---------------------------\n");
return true;
error:
return false;
} }
void bool
rb_vmdebug_proc_dump_raw(rb_proc_t *proc, FILE *errout) rb_vmdebug_proc_dump_raw(rb_proc_t *proc, FILE *errout)
{ {
const rb_env_t *env; const rb_env_t *env;
@ -266,17 +280,21 @@ rb_vmdebug_proc_dump_raw(rb_proc_t *proc, FILE *errout)
VALUE val = rb_inspect(vm_block_self(&proc->block)); VALUE val = rb_inspect(vm_block_self(&proc->block));
selfstr = StringValueCStr(val); selfstr = StringValueCStr(val);
fprintf(errout, "-- proc -------------------\n"); kprintf("-- proc -------------------\n");
fprintf(errout, "self: %s\n", selfstr); kprintf("self: %s\n", selfstr);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&proc->block)); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&proc->block));
rb_vmdebug_env_dump_raw(env, vm_block_ep(&proc->block), errout); rb_vmdebug_env_dump_raw(env, vm_block_ep(&proc->block), errout);
return true;
error:
return false;
} }
void bool
rb_vmdebug_stack_dump_th(VALUE thval, FILE *errout) rb_vmdebug_stack_dump_th(VALUE thval, FILE *errout)
{ {
rb_thread_t *target_th = rb_thread_ptr(thval); rb_thread_t *target_th = rb_thread_ptr(thval);
rb_vmdebug_stack_dump_raw(target_th->ec, target_th->ec->cfp, errout); return rb_vmdebug_stack_dump_raw(target_th->ec, target_th->ec->cfp, errout);
} }
#if VMDEBUG > 2 #if VMDEBUG > 2
@ -325,12 +343,12 @@ vm_stack_dump_each(const rb_execution_context_t *ec, const rb_control_frame_t *c
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
rstr = rb_inspect(*ptr); rstr = rb_inspect(*ptr);
fprintf(errout, " arg %2d: %8s (%p)\n", i, StringValueCStr(rstr), kprintf(" arg %2d: %8s (%p)\n", i, StringValueCStr(rstr),
(void *)ptr++); (void *)ptr++);
} }
for (; i < local_table_size - 1; i++) { for (; i < local_table_size - 1; i++) {
rstr = rb_inspect(*ptr); rstr = rb_inspect(*ptr);
fprintf(errout, " local %2d: %8s (%p)\n", i, StringValueCStr(rstr), kprintf(" local %2d: %8s (%p)\n", i, StringValueCStr(rstr),
(void *)ptr++); (void *)ptr++);
} }
@ -347,7 +365,7 @@ vm_stack_dump_each(const rb_execution_context_t *ec, const rb_control_frame_t *c
rstr = rb_inspect(*ptr); rstr = rb_inspect(*ptr);
break; break;
} }
fprintf(errout, " stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr), kprintf(" stack %2d: %8s (%"PRIdPTRDIFF")\n", i, StringValueCStr(rstr),
(ptr - ec->vm_stack)); (ptr - ec->vm_stack));
} }
} }
@ -365,7 +383,7 @@ vm_stack_dump_each(const rb_execution_context_t *ec, const rb_control_frame_t *c
} }
#endif #endif
void bool
rb_vmdebug_debug_print_register(const rb_execution_context_t *ec, FILE *errout) rb_vmdebug_debug_print_register(const rb_execution_context_t *ec, FILE *errout)
{ {
rb_control_frame_t *cfp = ec->cfp; rb_control_frame_t *cfp = ec->cfp;
@ -382,17 +400,21 @@ rb_vmdebug_debug_print_register(const rb_execution_context_t *ec, FILE *errout)
} }
cfpi = ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size)) - cfp; cfpi = ((rb_control_frame_t *)(ec->vm_stack + ec->vm_stack_size)) - cfp;
fprintf(errout, " [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n", kprintf(" [PC] %04"PRIdPTRDIFF", [SP] %04"PRIdPTRDIFF", [EP] %04"PRIdPTRDIFF", [CFP] %04"PRIdPTRDIFF"\n",
pc, (cfp->sp - ec->vm_stack), ep, cfpi); pc, (cfp->sp - ec->vm_stack), ep, cfpi);
return true;
error:
return false;
} }
void bool
rb_vmdebug_thread_dump_regs(VALUE thval, FILE *errout) rb_vmdebug_thread_dump_regs(VALUE thval, FILE *errout)
{ {
rb_vmdebug_debug_print_register(rb_thread_ptr(thval)->ec, errout); return rb_vmdebug_debug_print_register(rb_thread_ptr(thval)->ec, errout);
} }
void bool
rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *errout) rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, const VALUE *_pc, FILE *errout)
{ {
const rb_iseq_t *iseq = cfp->iseq; const rb_iseq_t *iseq = cfp->iseq;
@ -402,10 +424,10 @@ rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_fr
int i; int i;
for (i=0; i<(int)VM_CFP_CNT(ec, cfp); i++) { for (i=0; i<(int)VM_CFP_CNT(ec, cfp); i++) {
printf(" "); kprintf(" ");
} }
printf("| "); kprintf("| ");
if(0)printf("[%03ld] ", (long)(cfp->sp - ec->vm_stack)); if(0) kprintf("[%03ld] ", (long)(cfp->sp - ec->vm_stack));
/* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(ec, cfp)); */ /* printf("%3"PRIdPTRDIFF" ", VM_CFP_CNT(ec, cfp)); */
if (pc >= 0) { if (pc >= 0) {
@ -416,20 +438,24 @@ rb_vmdebug_debug_print_pre(const rb_execution_context_t *ec, const rb_control_fr
} }
#if VMDEBUG > 3 #if VMDEBUG > 3
fprintf(errout, " (1)"); kprintf(" (1)");
rb_vmdebug_debug_print_register(errout, ec); rb_vmdebug_debug_print_register(errout, ec);
#endif #endif
return true;
error:
return false;
} }
void bool
rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout) rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_frame_t *cfp, FILE *errout)
{ {
#if VMDEBUG > 9 #if VMDEBUG > 9
rb_vmdebug_stack_dump_raw(ec, cfp, errout); if (!rb_vmdebug_stack_dump_raw(ec, cfp, errout)) goto errout;
#endif #endif
#if VMDEBUG > 3 #if VMDEBUG > 3
fprintf(errout, " (2)"); kprintf(" (2)");
rb_vmdebug_debug_print_register(errout, ec); rb_vmdebug_debug_print_register(errout, ec);
#endif #endif
/* stack_dump_raw(ec, cfp); */ /* stack_dump_raw(ec, cfp); */
@ -438,8 +464,14 @@ rb_vmdebug_debug_print_post(const rb_execution_context_t *ec, const rb_control_f
/* stack_dump_thobj(ec); */ /* stack_dump_thobj(ec); */
vm_stack_dump_each(ec, ec->cfp, errout); vm_stack_dump_each(ec, ec->cfp, errout);
printf kprintf
("--------------------------------------------------------------\n"); ("--------------------------------------------------------------\n");
#endif
return true;
#if VMDEBUG > 2
error:
return false;
#endif #endif
} }
@ -449,10 +481,11 @@ rb_vmdebug_thread_dump_state(FILE *errout, VALUE self)
rb_thread_t *th = rb_thread_ptr(self); rb_thread_t *th = rb_thread_ptr(self);
rb_control_frame_t *cfp = th->ec->cfp; rb_control_frame_t *cfp = th->ec->cfp;
fprintf(errout, "Thread state dump:\n"); kprintf("Thread state dump:\n");
fprintf(errout, "pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp); kprintf("pc : %p, sp : %p\n", (void *)cfp->pc, (void *)cfp->sp);
fprintf(errout, "cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep); kprintf("cfp: %p, ep : %p\n", (void *)cfp, (void *)cfp->ep);
error:
return Qnil; return Qnil;
} }
@ -746,19 +779,20 @@ dump_thread(void *arg)
info->MaxNameLen = MAX_SYM_NAME; info->MaxNameLen = MAX_SYM_NAME;
if (pSymFromAddr(ph, addr, &displacement, info)) { if (pSymFromAddr(ph, addr, &displacement, info)) {
if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath))) if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
fprintf(errout, "%s", libpath); kprintf("%s", libpath);
fprintf(errout, "(%s+0x%"PRI_64_PREFIX"x)", kprintf("(%s+0x%"PRI_64_PREFIX"x)",
info->Name, displacement); info->Name, displacement);
} }
fprintf(errout, " [0x%p]", (void *)(VALUE)addr); kprintf(" [0x%p]", (void *)(VALUE)addr);
memset(&line, 0, sizeof(line)); memset(&line, 0, sizeof(line));
line.SizeOfStruct = sizeof(line); line.SizeOfStruct = sizeof(line);
if (pSymGetLineFromAddr64(ph, addr, &tmp, &line)) if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
fprintf(errout, " %s:%lu", line.FileName, line.LineNumber); kprintf(" %s:%lu", line.FileName, line.LineNumber);
fprintf(errout, "\n"); kprintf("\n");
} }
} }
error:
ResumeThread(th); ResumeThread(th);
} }
CloseHandle(th); CloseHandle(th);
@ -783,7 +817,7 @@ rb_print_backtrace(FILE *errout)
if (syms) { if (syms) {
int i; int i;
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
fprintf(errout, "%s\n", syms[i]); kprintf("%s\n", syms[i]);
} }
free(syms); free(syms);
} }
@ -827,21 +861,24 @@ print_machine_register(FILE *errout, size_t reg, const char *reg_name, int col_c
ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%.*" PRIxSIZE, reg_name, size_width, reg); ret = snprintf(buf, sizeof(buf), " %3.3s: 0x%.*" PRIxSIZE, reg_name, size_width, reg);
if (col_count + ret > max_col) { if (col_count + ret > max_col) {
fputs("\n", errout); kputs("\n");
col_count = 0; col_count = 0;
} }
col_count += ret; col_count += ret;
fputs(buf, errout); kputs(buf);
return col_count; return col_count;
error:
return -1;
} }
static void static bool
rb_dump_machine_register(FILE *errout, const ucontext_t *ctx) rb_dump_machine_register(FILE *errout, const ucontext_t *ctx)
{ {
int col_count = 0; int col_count = 0;
if (!ctx) return; if (!ctx) return true;
fprintf(errout, "-- Machine register context " kprintf("-- Machine register context "
"------------------------------------------------\n"); "------------------------------------------------\n");
# if defined __linux__ # if defined __linux__
@ -1034,13 +1071,17 @@ rb_dump_machine_register(FILE *errout, const ucontext_t *ctx)
# endif # endif
} }
# endif # endif
fprintf(errout, "\n\n"); kprintf("\n\n");
return true;
error:
return false;
} }
#else #else
# define rb_dump_machine_register(errout, ctx) ((void)0) # define rb_dump_machine_register(errout, ctx) ((void)0)
#endif /* dump_machine_register */ #endif /* dump_machine_register */
void bool
rb_vm_bugreport(const void *ctx, FILE *errout) rb_vm_bugreport(const void *ctx, FILE *errout)
{ {
const char *cmd = getenv("RUBY_ON_BUG"); const char *cmd = getenv("RUBY_ON_BUG");
@ -1058,8 +1099,8 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
{ {
static bool crashing = false; static bool crashing = false;
if (crashing) { if (crashing) {
fprintf(errout, "Crashed while printing bug report\n"); kprintf("Crashed while printing bug report\n");
return; return true;
} }
crashing = true; crashing = true;
} }
@ -1082,26 +1123,26 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
// If we get here, hopefully things are intact enough that // If we get here, hopefully things are intact enough that
// we can read these two numbers. It is an estimate because // we can read these two numbers. It is an estimate because
// we are reading without synchronization. // we are reading without synchronization.
fprintf(errout, "-- Threading information " kprintf("-- Threading information "
"---------------------------------------------------\n"); "---------------------------------------------------\n");
fprintf(errout, "Total ractor count: %u\n", vm->ractor.cnt); kprintf("Total ractor count: %u\n", vm->ractor.cnt);
fprintf(errout, "Ruby thread count for this ractor: %u\n", rb_ec_ractor_ptr(ec)->threads.cnt); kprintf("Ruby thread count for this ractor: %u\n", rb_ec_ractor_ptr(ec)->threads.cnt);
fputs("\n", errout); fputs("\n", errout);
} }
rb_dump_machine_register(errout, ctx); rb_dump_machine_register(errout, ctx);
#if USE_BACKTRACE || defined(_WIN32) #if USE_BACKTRACE || defined(_WIN32)
fprintf(errout, "-- C level backtrace information " kprintf("-- C level backtrace information "
"-------------------------------------------\n"); "-------------------------------------------\n");
rb_print_backtrace(errout); rb_print_backtrace(errout);
fprintf(errout, "\n"); kprintf("\n");
#endif /* USE_BACKTRACE */ #endif /* USE_BACKTRACE */
if (other_runtime_info || vm) { if (other_runtime_info || vm) {
fprintf(errout, "-- Other runtime information " kprintf("-- Other runtime information "
"-----------------------------------------------\n\n"); "-----------------------------------------------\n\n");
} }
if (vm && !rb_during_gc()) { if (vm && !rb_during_gc()) {
@ -1114,16 +1155,16 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
name = vm->progname; name = vm->progname;
if (name) { if (name) {
fprintf(errout, "* Loaded script: %.*s\n", kprintf("* Loaded script: %.*s\n",
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
fprintf(errout, "\n"); kprintf("\n");
} }
if (vm->loaded_features) { if (vm->loaded_features) {
fprintf(errout, "* Loaded features:\n\n"); kprintf("* Loaded features:\n\n");
for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) { for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
name = RARRAY_AREF(vm->loaded_features, i); name = RARRAY_AREF(vm->loaded_features, i);
if (RB_TYPE_P(name, T_STRING)) { if (RB_TYPE_P(name, T_STRING)) {
fprintf(errout, " %4d %.*s\n", i, kprintf(" %4d %.*s\n", i,
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
} }
else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) { else if (RB_TYPE_P(name, T_CLASS) || RB_TYPE_P(name, T_MODULE)) {
@ -1131,26 +1172,26 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
"class" : "module"; "class" : "module";
name = rb_search_class_path(rb_class_real(name)); name = rb_search_class_path(rb_class_real(name));
if (!RB_TYPE_P(name, T_STRING)) { if (!RB_TYPE_P(name, T_STRING)) {
fprintf(errout, " %4d %s:<unnamed>\n", i, type); kprintf(" %4d %s:<unnamed>\n", i, type);
continue; continue;
} }
fprintf(errout, " %4d %s:%.*s\n", i, type, kprintf(" %4d %s:%.*s\n", i, type,
LIMITED_NAME_LENGTH(name), RSTRING_PTR(name)); LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
} }
else { else {
VALUE klass = rb_search_class_path(rb_obj_class(name)); VALUE klass = rb_search_class_path(rb_obj_class(name));
if (!RB_TYPE_P(klass, T_STRING)) { if (!RB_TYPE_P(klass, T_STRING)) {
fprintf(errout, " %4d #<%p:%p>\n", i, kprintf(" %4d #<%p:%p>\n", i,
(void *)CLASS_OF(name), (void *)name); (void *)CLASS_OF(name), (void *)name);
continue; continue;
} }
fprintf(errout, " %4d #<%.*s:%p>\n", i, kprintf(" %4d #<%.*s:%p>\n", i,
LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass), LIMITED_NAME_LENGTH(klass), RSTRING_PTR(klass),
(void *)name); (void *)name);
} }
} }
} }
fprintf(errout, "\n"); kprintf("\n");
} }
{ {
@ -1158,7 +1199,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
{ {
FILE *fp = fopen(PROC_MAPS_NAME, "r"); FILE *fp = fopen(PROC_MAPS_NAME, "r");
if (fp) { if (fp) {
fprintf(errout, "* Process memory map:\n\n"); kprintf("* Process memory map:\n\n");
while (!feof(fp)) { while (!feof(fp)) {
char buff[0x100]; char buff[0x100];
@ -1168,7 +1209,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
} }
fclose(fp); fclose(fp);
fprintf(errout, "\n\n"); kprintf("\n\n");
} }
} }
#endif /* __linux__ */ #endif /* __linux__ */
@ -1182,14 +1223,14 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
mib[2] = KERN_PROC_PID; mib[2] = KERN_PROC_PID;
mib[3] = getpid(); mib[3] = getpid();
if (sysctl(mib, MIB_KERN_PROC_PID_LEN, &kp, &len, NULL, 0) == -1) { if (sysctl(mib, MIB_KERN_PROC_PID_LEN, &kp, &len, NULL, 0) == -1) {
fprintf(errout, "sysctl: %s\n", strerror(errno)); kprintf("sysctl: %s\n", strerror(errno));
} }
else { else {
struct procstat *prstat = procstat_open_sysctl(); struct procstat *prstat = procstat_open_sysctl();
fprintf(errout, "* Process memory map:\n\n"); kprintf("* Process memory map:\n\n");
procstat_vm(prstat, &kp); procstat_vm(prstat, &kp);
procstat_close(prstat); procstat_close(prstat);
fprintf(errout, "\n"); kprintf("\n");
} }
#endif /* __FreeBSD__ */ #endif /* __FreeBSD__ */
#ifdef __APPLE__ #ifdef __APPLE__
@ -1199,7 +1240,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT; mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT;
natural_t depth = 0; natural_t depth = 0;
fprintf(errout, "* Process memory map:\n\n"); kprintf("* Process memory map:\n\n");
while (1) { while (1) {
if (vm_region_recurse(mach_task_self(), &addr, &size, &depth, if (vm_region_recurse(mach_task_self(), &addr, &size, &depth,
(vm_region_recurse_info_t)&map, &count) != KERN_SUCCESS) { (vm_region_recurse_info_t)&map, &count) != KERN_SUCCESS) {
@ -1211,17 +1252,17 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
depth++; depth++;
} }
else { else {
fprintf(errout, "%lx-%lx %s%s%s", addr, (addr+size), kprintf("%lx-%lx %s%s%s", addr, (addr+size),
((map.protection & VM_PROT_READ) != 0 ? "r" : "-"), ((map.protection & VM_PROT_READ) != 0 ? "r" : "-"),
((map.protection & VM_PROT_WRITE) != 0 ? "w" : "-"), ((map.protection & VM_PROT_WRITE) != 0 ? "w" : "-"),
((map.protection & VM_PROT_EXECUTE) != 0 ? "x" : "-")); ((map.protection & VM_PROT_EXECUTE) != 0 ? "x" : "-"));
#ifdef HAVE_LIBPROC_H #ifdef HAVE_LIBPROC_H
char buff[PATH_MAX]; char buff[PATH_MAX];
if (proc_regionfilename(getpid(), addr, buff, sizeof(buff)) > 0) { if (proc_regionfilename(getpid(), addr, buff, sizeof(buff)) > 0) {
fprintf(errout, " %s", buff); kprintf(" %s", buff);
} }
#endif #endif
fprintf(errout, "\n"); kprintf("\n");
} }
addr += size; addr += size;
@ -1229,9 +1270,13 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
} }
#endif #endif
} }
return true;
error:
return false;
} }
void bool
rb_vmdebug_stack_dump_all_threads(void) rb_vmdebug_stack_dump_all_threads(void)
{ {
rb_thread_t *th = NULL; rb_thread_t *th = NULL;
@ -1241,10 +1286,14 @@ rb_vmdebug_stack_dump_all_threads(void)
// TODO: now it only shows current ractor // TODO: now it only shows current ractor
ccan_list_for_each(&r->threads.set, th, lt_node) { ccan_list_for_each(&r->threads.set, th, lt_node) {
#ifdef NON_SCALAR_THREAD_ID #ifdef NON_SCALAR_THREAD_ID
fprintf(errout, "th: %p, native_id: N/A\n", th); kprintf("th: %p, native_id: N/A\n", th);
#else #else
fprintf(errout, "th: %p, native_id: %p\n", (void *)th, (void *)(uintptr_t)th->nt->thread_id); kprintf("th: %p, native_id: %p\n", (void *)th, (void *)(uintptr_t)th->nt->thread_id);
#endif #endif
rb_vmdebug_stack_dump_raw(th->ec, th->ec->cfp, errout); if (!rb_vmdebug_stack_dump_raw(th->ec, th->ec->cfp, errout)) goto error;
} }
return true;
error:
return false;
} }