MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

improve formatting of error printout

+78 -102
+78 -102
src/crash.c
··· 13 13 #include "crash.h" 14 14 #include "internal.h" 15 15 #include "reactor.h" 16 + #include "cli/version.h" 16 17 17 18 #include "silver/engine.h" 18 19 #include "modules/assert.h" ··· 61 62 62 63 #ifdef __APPLE__ 63 64 #include <mach-o/dyld.h> 65 + #include <sys/sysctl.h> 66 + #elif defined(__linux__) 67 + #include <sys/utsname.h> 64 68 #endif 65 69 66 70 #if defined(__APPLE__) || defined(__linux__) || defined(__GLIBC__) ··· 221 225 #endif 222 226 } 223 227 228 + static const char *os_version(void) { 229 + static char version[128]; 230 + if (version[0]) return version; 231 + 232 + #ifdef _WIN32 233 + OSVERSIONINFOEXA info; 234 + memset(&info, 0, sizeof(info)); 235 + info.dwOSVersionInfoSize = sizeof(info); 236 + if (GetVersionExA((OSVERSIONINFOA *)&info)) { 237 + snprintf( 238 + version, sizeof(version), "%lu.%lu.%lu", 239 + (unsigned long)info.dwMajorVersion, 240 + (unsigned long)info.dwMinorVersion, 241 + (unsigned long)info.dwBuildNumber 242 + ); 243 + return version; 244 + } 245 + #elif defined(__APPLE__) 246 + size_t len = sizeof(version); 247 + if (sysctlbyname("kern.osproductversion", version, &len, NULL, 0) == 0 && version[0]) 248 + return version; 249 + #elif defined(__linux__) 250 + struct utsname info; 251 + if (uname(&info) == 0 && info.release[0]) { 252 + snprintf(version, sizeof(version), "%s", info.release); 253 + return version; 254 + } 255 + #endif 256 + snprintf(version, sizeof(version), "unknown"); 257 + return version; 258 + } 259 + 260 + static const char *os_display_name(void) { 261 + static char display[160]; 262 + if (!display[0]) snprintf(display, sizeof(display), "%s v%s", os_name(), os_version()); 263 + return display; 264 + } 265 + 224 266 static const char *arch_name(void) { 225 267 #if defined(__aarch64__) || defined(_M_ARM64) 226 268 return "arm64"; ··· 341 383 if (base && GetModuleFileNameA((HMODULE)(uintptr_t)base, module_path, (DWORD)sizeof(module_path)) > 0) 342 384 image = path_basename_const(module_path); 343 385 344 - // TODO: make dry 345 386 union { 346 387 SYMBOL_INFO info; 347 388 char storage[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; ··· 405 446 cb_puts(&p, ",\"target\":"); 406 447 cb_put_json_string(&p, ANT_TARGET_TRIPLE); 407 448 cb_puts(&p, ",\"os\":"); 408 - cb_put_json_string(&p, os_name()); 449 + cb_put_json_string(&p, os_display_name()); 409 450 cb_puts(&p, ",\"arch\":"); 410 451 cb_put_json_string(&p, arch_name()); 411 452 cb_puts(&p, ",\"kind\":"); ··· 533 574 } 534 575 #endif 535 576 577 + static void crash_report_print_upload_failed(void) { 578 + if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 579 + else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 580 + } 581 + 582 + static void crash_report_print_upload_error(const char *message) { 583 + crash_report_print_upload_failed(); 584 + if (message && *message) fprintf(stderr, "%s\n", message); 585 + } 586 + 536 587 static ant_value_t crash_report_noop(ant_t *js, ant_value_t *args, int nargs) { 537 588 if (crash_report_status_printed) return js_mkundef(); 538 589 crash_report_status_printed = true; 539 590 540 - // TODO: make dry 541 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 542 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 543 - 544 - if (args && nargs > 0) { 545 - const char *message = js_str(js, args[0]); 546 - if (message && *message) { 547 - fputs(message, stderr); 548 - fputc('\n', stderr); 549 - }} 550 - 591 + if (args && nargs > 0) crash_report_print_upload_error(js_str(js, args[0])); 592 + else crash_report_print_upload_failed(); 593 + 551 594 return js_mkundef(); 552 595 } 553 596 ··· 560 603 if (!s || len == 0) { 561 604 if (!crash_report_status_printed) { 562 605 crash_report_status_printed = true; 563 - // TODO: make dry 564 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 565 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 606 + crash_report_print_upload_failed(); 566 607 } 567 608 return js_mkundef(); 568 609 } ··· 581 622 if (!is_callable(text_fn)) { 582 623 if (!crash_report_status_printed) { 583 624 crash_report_status_printed = true; 584 - // TODO: make dry 585 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 586 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 625 + crash_report_print_upload_failed(); 587 626 fputs("Response.text is not available.\n", stderr); 588 627 } 589 628 return js_mkundef(); ··· 749 788 } 750 789 751 790 static void crash_print_report_summary(ant_t *js, ant_value_t report, ant_value_t argv, bool upload, bool trace, unsigned long long pid) { 752 - crprintf_var("version", ANT_VERSION); 753 - crprintf_var("target", ANT_TARGET_TRIPLE); 754 - crprintf_var("git_hash", ANT_GIT_HASH); 755 - 756 - crprintf_var("os_name", os_name()); 757 - crprintf_var("os_version", "os_version"); 758 - 759 791 size_t code_len = 0, addr_len = 0, reason_len = 0; 760 792 761 793 const char *code = crash_get_string(js, report, "code", &code_len, "SIGNAL"); ··· 771 803 char peak_rss_text[32]; 772 804 crash_format_bytes(peak_rss_text, sizeof(peak_rss_text), peak_rss); 773 805 774 - fprintf(stderr, "=== (%llu) ===================================================\n", pid); 775 - 776 - // TODO: Ant v<version> (<git_hash>) <arch> 777 - crfprintf(stderr, "<dim>Ant {version} {git_hash} {target}\n"); 778 - crfprintf(stderr, "<dim>{os_name} {os_version}\n"); 779 - 806 + fprintf(stderr, "=== (%llu) ===================================================\n", pid); 807 + 808 + crfprintf(stderr, "<dim>Ant v%s (%s) %s</>\n", ant_semver(), ANT_GIT_HASH, ANT_TARGET_TRIPLE); 809 + crfprintf(stderr, "<dim>%s</>\n", os_display_name()); 810 + 780 811 crash_print_args(js, argv); 781 - 782 - crfprintf(stderr, "<dim>Summary: %s (%.*s) with signal %d\n", detail, code_len, code, signal_number); 783 - crfprintf(stderr, "<dim>Elapsed: %llums | RSS Peak: %s\n\n", elapsed, peak_rss_text); 784 - crfprintf(stderr, "<red>panic</red><dim>(main thread):</> %.*s at address %.*s \n", reason_len, reason, addr_len, addr); 785 - 812 + 813 + crfprintf(stderr, "<dim>Summary: %s (%.*s) with signal %d</>\n", detail, (int)code_len, code, signal_number); 814 + crfprintf(stderr, "<dim>Elapsed: %llums | RSS Peak: %s</>\n\n", elapsed, peak_rss_text); 815 + crfprintf(stderr, "<red>panic</red><dim>(main thread):</> %.*s at address %.*s \n", (int)reason_len, reason, (int)addr_len, addr); 816 + 786 817 crfprintf(stderr, "oh no<dim>:</> Ant has crashed. This indicates a bug in Ant, not your code.\n\n"); 787 818 if (trace) crash_print_frames(js, report); 788 819 ··· 805 836 806 837 ant_value_t wrapper_json = js_mkstr(js, payload, payload_len); 807 838 ant_value_t wrapper = json_parse_value(js, wrapper_json); 808 - 839 + 809 840 if (is_err(wrapper) || !is_object_type(wrapper)) { 810 - // TODO: make this dry 811 - crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 841 + crash_report_print_upload_failed(); 812 842 free(payload); 813 843 return EXIT_FAILURE; 814 844 } 815 845 816 846 ant_value_t report = crash_get(js, wrapper, "report"); 817 847 if (!is_object_type(report)) { 818 - crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 848 + crash_report_print_upload_failed(); 819 849 free(payload); 820 850 return EXIT_FAILURE; 821 851 } ··· 836 866 837 867 ant_value_t report_json = js_json_stringify(js, &report, 1); 838 868 if (vtype(report_json) != T_STR) { 839 - // TODO: make this dry 840 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 841 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 869 + crash_report_print_upload_failed(); 842 870 free(payload); 843 871 return EXIT_FAILURE; 844 872 } ··· 846 874 size_t report_payload_len = 0; 847 875 const char *report_payload = js_getstr(js, report_json, &report_payload_len); 848 876 if (!report_payload) { 849 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 850 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 877 + crash_report_print_upload_failed(); 851 878 free(payload); 852 879 return EXIT_FAILURE; 853 880 } ··· 866 893 867 894 ant_value_t fetch_args[2] = { js_mkstr(js, url, strlen(url)), init }; 868 895 ant_value_t fetch_promise = ant_fetch(js, fetch_args, 2); 869 - 896 + 870 897 if (is_err(fetch_promise)) { 871 898 crash_report_status_printed = true; 872 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 873 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 874 - const char *message = js_str(js, fetch_promise); 875 - if (message && *message) fprintf(stderr, "%s\n", message); 899 + crash_report_print_upload_error(js_str(js, fetch_promise)); 876 900 free(payload); 877 901 return EXIT_FAILURE; 878 902 } ··· 882 906 js_mkfun(crash_report_response_text), 883 907 js_mkfun(crash_report_noop) 884 908 ); 885 - 909 + 886 910 promise_mark_handled(fetch_promise); 887 911 if (is_err(report_promise)) { 888 912 crash_report_status_printed = true; 889 - // TODO: make this dry 890 - if (crash_report_status_inline) crfprintf(stderr, "\r\033[2K <red>Crash report upload failed.</red>\n"); 891 - else crfprintf(stderr, "<red>Crash report upload failed.</red>\n"); 892 - const char *message = js_str(js, report_promise); 893 - if (message && *message) fprintf(stderr, "%s\n", message); 913 + crash_report_print_upload_error(js_str(js, report_promise)); 894 914 free(payload); 895 915 return EXIT_FAILURE; 896 916 } 897 - 917 + 898 918 promise_mark_handled(report_promise); 899 919 js_run_event_loop(js); 900 920 free(payload); ··· 1087 1107 if (!ok || (frame.AddrPC.Offset == prev_pc && frame.AddrStack.Offset == prev_sp)) break; 1088 1108 } 1089 1109 return count; 1090 - } 1091 - 1092 - static void print_windows_backtrace(EXCEPTION_POINTERS *exc) { 1093 - if (!exc || !exc->ContextRecord) { 1094 - fprintf(stderr, " (no exception context available)\n"); 1095 - return; 1096 - } 1097 - 1098 - HANDLE process = GetCurrentProcess(); 1099 - SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); 1100 - if (!SymInitialize(process, NULL, TRUE)) { 1101 - fprintf(stderr, " (SymInitialize failed: %lu)\n", GetLastError()); 1102 - return; 1103 - } 1104 - 1105 - uintptr_t frames[ANT_CRASH_FRAME_MAX] = {0}; 1106 - int frame_count = collect_windows_frames(exc, frames, ANT_CRASH_FRAME_MAX); 1107 - 1108 - union { 1109 - SYMBOL_INFO info; 1110 - char storage[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; 1111 - } symbol_buf; 1112 - 1113 - SYMBOL_INFO *symbol = &symbol_buf.info; 1114 - memset(&symbol_buf, 0, sizeof(symbol_buf)); 1115 - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); 1116 - symbol->MaxNameLen = MAX_SYM_NAME; 1117 - 1118 - for (int i = 0; i < frame_count; i++) { 1119 - DWORD64 addr = (DWORD64)frames[i]; 1120 - DWORD64 displacement = 0; 1121 - 1122 - fprintf(stderr, "%d 0x%016llx", i, (unsigned long long)addr); 1123 - if (SymFromAddr(process, addr, &displacement, symbol)) 1124 - fprintf(stderr, " %s + %llu", symbol->Name, (unsigned long long)displacement); 1125 - 1126 - IMAGEHLP_LINE64 line; 1127 - DWORD line_disp = 0; 1128 - memset(&line, 0, sizeof(line)); 1129 - line.SizeOfStruct = sizeof(line); 1130 - if (SymGetLineFromAddr64(process, addr, &line_disp, &line)) 1131 - fprintf(stderr, " (%s:%lu)", line.FileName, line.LineNumber); 1132 - fputc('\n', stderr); 1133 - } 1134 1110 } 1135 1111 1136 1112 static LONG WINAPI windows_crash_handler(EXCEPTION_POINTERS *exc) {