void rb_vm_bugreport(void) { if (GET_THREAD()->vm) { int i = 0; SDR(); if (rb_backtrace_each(bugreport_backtrace, &i)) { fputs("\n", stderr); } } #if HAVE_BACKTRACE #define MAX_NATIVE_TRACE 1024 { static void *trace[MAX_NATIVE_TRACE]; int n = backtrace(trace, MAX_NATIVE_TRACE); char **syms = backtrace_symbols(trace, n); int i; fprintf(stderr, "-- C level backtrace information " "-------------------------------------------\n"); if (syms) { for (i=0; i<n; i++) { fprintf(stderr, "%s\n", syms[i]); } free(syms); } fprintf(stderr, "\n"); } #endif }
static char * load_lock(const char *ftptr) { st_data_t data; st_table *loading_tbl = get_loading_table(); if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) { /* partial state */ ftptr = ruby_strdup(ftptr); data = (st_data_t)rb_thread_shield_new(); st_insert(loading_tbl, (st_data_t)ftptr, data); return (char *)ftptr; } else if (imemo_type_p(data, imemo_memo)) { struct MEMO *memo = MEMO_CAST(data); void (*init)(void) = (void (*)(void))memo->u3.func; data = (st_data_t)rb_thread_shield_new(); st_insert(loading_tbl, (st_data_t)ftptr, data); (*init)(); return (char *)""; } if (RTEST(ruby_verbose)) { VALUE warning = rb_warning_string("loading in progress, circular require considered harmful - %s", ftptr); rb_backtrace_each(rb_str_append, warning); rb_warning("%"PRIsVALUE, warning); } switch (rb_thread_shield_wait((VALUE)data)) { case Qfalse: case Qnil: return 0; } return (char *)ftptr; }
/* the return value of this will be eventually garbage collected, * therefore it is safe to use only from within gdb. I want this to * depend as little as possible on ruby itself, in order to ensure * that I can call this from strange places from gdb. */ char* ruby_gdb_backtrace() { char *c = NULL; rb_backtrace_each(backtrace_iter_fn, &c); return c; }
void rb_vm_bugreport(void) { rb_vm_t *vm = GET_VM(); if (vm) { int i = 0; SDR(); if (rb_backtrace_each(bugreport_backtrace, &i)) { fputs("\n", stderr); } } #if HAVE_BACKTRACE || defined(_WIN32) fprintf(stderr, "-- C level backtrace information " "-------------------------------------------\n"); { #if defined __MACH__ && defined __APPLE__ fprintf(stderr, "\n"); fprintf(stderr, " See Crash Report log file under " "~/Library/Logs/CrashReporter or\n"); fprintf(stderr, " /Library/Logs/CrashReporter, for " "the more detail of.\n"); #elif HAVE_BACKTRACE #define MAX_NATIVE_TRACE 1024 static void *trace[MAX_NATIVE_TRACE]; int n = backtrace(trace, MAX_NATIVE_TRACE); char **syms = backtrace_symbols(trace, n); if (syms) { #ifdef USE_ELF rb_dump_backtrace_with_lines(n, trace, syms); #else int i; for (i=0; i<n; i++) { fprintf(stderr, "%s\n", syms[i]); } #endif free(syms); } #elif defined(_WIN32) DWORD tid = GetCurrentThreadId(); HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid); if (th != (HANDLE)-1) WaitForSingleObject(th, INFINITE); #endif } fprintf(stderr, "\n"); #endif /* HAVE_BACKTRACE */ fprintf(stderr, "-- Other runtime information " "-----------------------------------------------\n\n"); { int i; fprintf(stderr, "* Loaded script: %s\n", StringValueCStr(vm->progname)); fprintf(stderr, "\n"); fprintf(stderr, "* Loaded features:\n\n"); for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) { fprintf(stderr, " %4d %s\n", i, StringValueCStr(RARRAY_PTR(vm->loaded_features)[i])); } fprintf(stderr, "\n"); #if __linux__ { FILE *fp = fopen("/proc/self/maps", "r"); if (fp) { fprintf(stderr, "* Process memory map:\n\n"); while (!feof(fp)) { char buff[0x100]; size_t rn = fread(buff, 1, 0x100, fp); fwrite(buff, 1, rn, stderr); } fclose(fp); fprintf(stderr, "\n\n"); } } #endif /* __linux__ */ } }