Dump backtraces to an arbitrary stream when using libprocstat

This commit is contained in:
Nobuyoshi Nakada 2023-09-26 09:02:37 +09:00
parent d2cc4437a1
commit 5eef125afe
No known key found for this signature in database
GPG Key ID: 3582D74E1FEE4465
2 changed files with 20 additions and 20 deletions

View File

@ -6,7 +6,7 @@
# define KVME_TYPE_MGTDEVICE 8 # define KVME_TYPE_MGTDEVICE 8
# endif # endif
void void
procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp) procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp, FILE *errout)
{ {
struct kinfo_vmentry *freep, *kve; struct kinfo_vmentry *freep, *kve;
int ptrwidth; int ptrwidth;
@ -17,7 +17,7 @@ procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
#else #else
ptrwidth = 2*sizeof(void *) + 2; ptrwidth = 2*sizeof(void *) + 2;
#endif #endif
fprintf(stderr, "%*s %*s %3s %4s %4s %3s %3s %4s %-2s %-s\n", fprintf(errout, "%*s %*s %3s %4s %4s %3s %3s %4s %-2s %-s\n",
ptrwidth, "START", ptrwidth, "END", "PRT", "RES", ptrwidth, "START", ptrwidth, "END", "PRT", "RES",
"P""RES", "REF", "SHD", "FL", "TP", "PATH"); "P""RES", "REF", "SHD", "FL", "TP", "PATH");
@ -30,20 +30,20 @@ procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
return; return;
for (i = 0; i < cnt; i++) { for (i = 0; i < cnt; i++) {
kve = &freep[i]; kve = &freep[i];
fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_start); fprintf(errout, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_start);
fprintf(stderr, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_end); fprintf(errout, "%#*jx ", ptrwidth, (uintmax_t)kve->kve_end);
fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-"); fprintf(errout, "%s", kve->kve_protection & KVME_PROT_READ ? "r" : "-");
fprintf(stderr, "%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-"); fprintf(errout, "%s", kve->kve_protection & KVME_PROT_WRITE ? "w" : "-");
fprintf(stderr, "%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-"); fprintf(errout, "%s ", kve->kve_protection & KVME_PROT_EXEC ? "x" : "-");
fprintf(stderr, "%4d ", kve->kve_resident); fprintf(errout, "%4d ", kve->kve_resident);
fprintf(stderr, "%4d ", kve->kve_private_resident); fprintf(errout, "%4d ", kve->kve_private_resident);
fprintf(stderr, "%3d ", kve->kve_ref_count); fprintf(errout, "%3d ", kve->kve_ref_count);
fprintf(stderr, "%3d ", kve->kve_shadow_count); fprintf(errout, "%3d ", kve->kve_shadow_count);
fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-"); fprintf(errout, "%-1s", kve->kve_flags & KVME_FLAG_COW ? "C" : "-");
fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" : fprintf(errout, "%-1s", kve->kve_flags & KVME_FLAG_NEEDS_COPY ? "N" :
"-"); "-");
fprintf(stderr, "%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-"); fprintf(errout, "%-1s", kve->kve_flags & KVME_FLAG_SUPER ? "S" : "-");
fprintf(stderr, "%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" : fprintf(errout, "%-1s ", kve->kve_flags & KVME_FLAG_GROWS_UP ? "U" :
kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-"); kve->kve_flags & KVME_FLAG_GROWS_DOWN ? "D" : "-");
switch (kve->kve_type) { switch (kve->kve_type) {
case KVME_TYPE_NONE: case KVME_TYPE_NONE:
@ -78,8 +78,8 @@ procstat_vm(struct procstat *procstat, struct kinfo_proc *kipp)
str = "??"; str = "??";
break; break;
} }
fprintf(stderr, "%-2s ", str); fprintf(errout, "%-2s ", str);
fprintf(stderr, "%-s\n", kve->kve_path); fprintf(errout, "%-s\n", kve->kve_path);
} }
free(freep); free(freep);
} }

View File

@ -1121,7 +1121,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
if (vm && ec) { if (vm && ec) {
rb_vmdebug_stack_dump_raw(ec, ec->cfp, errout); rb_vmdebug_stack_dump_raw(ec, ec->cfp, errout);
rb_backtrace_print_as_bugreport(errout); rb_backtrace_print_as_bugreport(errout);
fputs("\n", errout); kputs("\n");
// 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.
@ -1129,7 +1129,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
"---------------------------------------------------\n"); "---------------------------------------------------\n");
kprintf("Total ractor count: %u\n", vm->ractor.cnt); kprintf("Total ractor count: %u\n", vm->ractor.cnt);
kprintf("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); kputs("\n");
} }
rb_dump_machine_register(errout, ctx); rb_dump_machine_register(errout, ctx);
@ -1230,7 +1230,7 @@ rb_vm_bugreport(const void *ctx, FILE *errout)
else { else {
struct procstat *prstat = procstat_open_sysctl(); struct procstat *prstat = procstat_open_sysctl();
kprintf("* Process memory map:\n\n"); kprintf("* Process memory map:\n\n");
procstat_vm(prstat, &kp); procstat_vm(prstat, &kp, errout);
procstat_close(prstat); procstat_close(prstat);
kprintf("\n"); kprintf("\n");
} }