diff options
author | 2022-11-11 00:19:50 -0800 | |
---|---|---|
committer | 2022-11-11 00:20:42 -0800 | |
commit | 2432150321d94eae21013d2175a96e557fd207e5 (patch) | |
tree | e34fe8ed3ffc4aa41d749f943239186f27ae2b8e | |
parent | 38141e3aa7c2db5b01a6fd9a97776f9257a10049 (diff) | |
download | bun-2432150321d94eae21013d2175a96e557fd207e5.tar.gz bun-2432150321d94eae21013d2175a96e557fd207e5.tar.zst bun-2432150321d94eae21013d2175a96e557fd207e5.zip |
Replace `libbacktrace` with `WTFGetBacktrace`
-rw-r--r-- | .gitmodules | 7 | ||||
-rw-r--r-- | Dockerfile | 23 | ||||
-rw-r--r-- | Makefile | 14 | ||||
-rw-r--r-- | build.zig | 7 | ||||
-rw-r--r-- | src/bun.js/bindings/exports.zig | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/wtf-bindings.cpp | 34 | ||||
-rw-r--r-- | src/bun.js/module_loader.zig | 1 | ||||
-rw-r--r-- | src/crash_reporter.zig | 50 | ||||
-rw-r--r-- | src/deps/backtrace.zig | 148 | ||||
-rw-r--r-- | src/main.zig | 8 | ||||
-rw-r--r-- | src/report.zig | 20 |
11 files changed, 108 insertions, 206 deletions
diff --git a/.gitmodules b/.gitmodules index 231555d2d..0030d7cd9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -41,13 +41,6 @@ ignore = dirty depth = 1 shallow = true fetchRecurseSubmodules = false -[submodule "src/deps/libbacktrace"] -path = src/deps/libbacktrace -url = https://github.com/ianlancetaylor/libbacktrace -ignore = dirty -depth = 1 -shallow = true -fetchRecurseSubmodules = false [submodule "src/deps/lol-html"] path = src/deps/lol-html url = https://github.com/cloudflare/lol-html diff --git a/Dockerfile b/Dockerfile index 013eeffc6..4cf3e48c3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -222,27 +222,6 @@ ENV CPU_TARGET=${CPU_TARGET} RUN install_packages libtcc-dev && cp /usr/lib/$(uname -m)-linux-gnu/libtcc.a ${BUN_DEPS_OUT_DIR} -FROM bun-base as libbacktrace - -ARG DEBIAN_FRONTEND -ARG GITHUB_WORKSPACE -ARG ZIG_PATH -# Directory extracts to "bun-webkit" -ARG WEBKIT_DIR -ARG BUN_RELEASE_DIR -ARG BUN_DEPS_OUT_DIR -ARG BUN_DIR -ARG CPU_TARGET -ENV CPU_TARGET=${CPU_TARGET} - -COPY Makefile ${BUN_DIR}/Makefile -COPY src/deps/libbacktrace ${BUN_DIR}/src/deps/libbacktrace - -WORKDIR $BUN_DIR - -RUN cd $BUN_DIR && \ - make libbacktrace && rm -rf src/deps/libbacktrace Makefile - FROM bun-base as boringssl RUN install_packages golang @@ -466,7 +445,6 @@ COPY --from=oniguruma ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=picohttp ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/ COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=uws ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/ -COPY --from=libbacktrace ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=tinycc ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ # Required for `make webcrypto` @@ -523,7 +501,6 @@ ENV LIB_ICU_PATH=${WEBKIT_DIR}/lib COPY --from=zlib ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=libarchive ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=boringssl ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ -COPY --from=libbacktrace ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=lolhtml ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ COPY --from=mimalloc ${BUN_DEPS_OUT_DIR}/*.o ${BUN_DEPS_OUT_DIR}/ COPY --from=oniguruma ${BUN_DEPS_OUT_DIR}/*.a ${BUN_DEPS_OUT_DIR}/ @@ -397,8 +397,7 @@ MINIMUM_ARCHIVE_FILES = -L$(BUN_DEPS_OUT_DIR) \ -lssl \ -lcrypto \ -llolhtml \ - -lonig \ - $(BUN_DEPS_OUT_DIR)/libbacktrace.a \ + -lonig ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MINIMUM_ARCHIVE_FILES) \ -larchive \ @@ -497,7 +496,7 @@ builtins: ## to generate builtins generate-builtins: builtins .PHONY: vendor-without-check -vendor-without-check: npm-install node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive libbacktrace lolhtml usockets uws tinycc oniguruma +vendor-without-check: npm-install node-fallbacks runtime_js fallback_decoder bun_error mimalloc picohttp zlib boringssl libarchive lolhtml usockets uws tinycc oniguruma BUN_TYPES_REPO_PATH ?= $(realpath packages/bun-types) @@ -549,13 +548,6 @@ boringssl-debug: boringssl-build-debug boringssl-copy compile-ffi-test: clang $(OPTIMIZATION_LEVEL) -shared -undefined dynamic_lookup -o /tmp/bun-ffi-test.dylib -fPIC ./test/bun.js/ffi-test.c -.PHONY: libbacktrace -libbacktrace: - cd $(BUN_DEPS_DIR)/libbacktrace && \ - CFLAGS="$(CFLAGS)" CC=$(CC) ./configure --disable-shared --enable-static --with-pic && \ - make -j$(CPUS) && \ - cp ./.libs/libbacktrace.a $(BUN_DEPS_OUT_DIR)/libbacktrace.a - .PHONY: oniguruma oniguruma: cd $(BUN_DEPS_DIR)/oniguruma && \ @@ -854,7 +846,7 @@ clone-submodules: git -c submodule."src/bun.js/WebKit".update=none submodule update --init --recursive --depth=1 --progress .PHONY: devcontainer -devcontainer: $(OBJ_DIR) $(DEBUG_OBJ_DIR) clone-submodules libbacktrace mimalloc zlib libarchive boringssl picohttp identifier-cache node-fallbacks npm-install api analytics bun_error fallback_decoder bindings uws lolhtml usockets tinycc runtime_js_dev sqlite oniguruma webcrypto-debug webcrypto +devcontainer: $(OBJ_DIR) $(DEBUG_OBJ_DIR) clone-submodules mimalloc zlib libarchive boringssl picohttp identifier-cache node-fallbacks npm-install api analytics bun_error fallback_decoder bindings uws lolhtml usockets tinycc runtime_js_dev sqlite oniguruma webcrypto-debug webcrypto .PHONY: devcontainer-build devcontainer-build: @@ -56,11 +56,6 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar .source = pkgPath("src/thread_pool.zig"), }; - var crash_reporter: std.build.Pkg = .{ - .name = "crash_reporter", - .source = pkgPath("src/deps/backtrace.zig"), - }; - var picohttp: std.build.Pkg = .{ .name = "picohttp", .source = pkgPath("src/deps/picohttp.zig"), @@ -166,7 +161,6 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar step.addPackage(http); step.addPackage(boringssl); step.addPackage(javascript_core); - step.addPackage(crash_reporter); step.addPackage(datetime); step.addPackage(lol_html); step.addPackage(uws); @@ -594,7 +588,6 @@ pub fn linkObjectFiles(b: *std.build.Builder, obj: *std.build.LibExeObjStep, tar .{ "libJavaScriptCore.a", "libJavaScriptCore.a" }, .{ "libWTF.a", "libWTF.a" }, .{ "libbmalloc.a", "libbmalloc.a" }, - .{ "libbacktrace.a", "libbacktrace.a" }, .{ "liblolhtml.a", "liblolhtml.a" }, .{ "uSockets.a", "uSockets.a" }, }); diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index e6ccc039e..2e2c5e556 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -26,7 +26,7 @@ const JSModuleLoader = JSC.JSModuleLoader; const JSModuleRecord = JSC.JSModuleRecord; const Microtask = JSC.Microtask; const JSPrivateDataPtr = @import("../base.zig").JSPrivateDataPtr; -const Backtrace = @import("../../deps/backtrace.zig"); +const Backtrace = @import("../../crash_reporter.zig"); const JSPrinter = @import("../../js_printer.zig"); const JSLexer = @import("../../js_lexer.zig"); const typeBaseName = @import("../../meta.zig").typeBaseName; diff --git a/src/bun.js/bindings/wtf-bindings.cpp b/src/bun.js/bindings/wtf-bindings.cpp index 561c83ffa..d1d73a891 100644 --- a/src/bun.js/bindings/wtf-bindings.cpp +++ b/src/bun.js/bindings/wtf-bindings.cpp @@ -1,6 +1,8 @@ #include "wtf-bindings.h" #include "wtf/text/Base64.h" +#include "wtf/StackTrace.h" + extern "C" void WTF__copyLCharsFromUCharSource(LChar* destination, const UChar* source, size_t length) { WTF::StringImpl::copyCharacters(destination, source, length); @@ -11,4 +13,36 @@ extern "C" JSC::EncodedJSValue WTF__toBase64URLStringValue(const uint8_t* bytes, WTF::String string = WTF::base64URLEncodeToString(reinterpret_cast<const LChar*>(bytes), static_cast<unsigned int>(length)); string.impl()->ref(); return JSC::JSValue::encode(JSC::jsString(globalObject->vm(), string)); +} + +extern "C" void Bun__crashReportWrite(void* ctx, const char* message, size_t length); +extern "C" void Bun__crashReportDumpStackTrace(void* ctx) +{ + static constexpr int framesToShow = 32; + static constexpr int framesToSkip = 4; + void* stack[framesToShow + framesToSkip]; + int frames = framesToShow + framesToSkip; + WTFGetBacktrace(stack, &frames); + bool isFirst = true; + WTF::StackTraceSymbolResolver { { stack, static_cast<size_t>(frames) } }.forEach([&](int frameNumber, void* stackFrame, const char* name) { + if (frameNumber < framesToSkip) + return; + + StringPrintStream out; + if (isFirst) { + isFirst = false; + if (name) + out.printf("\n%-3d %p %s", frameNumber, stackFrame, name); + else + out.printf("\n%-3d %p", frameNumber, stackFrame); + } else { + if (name) + out.printf("%-3d %p %s", frameNumber, stackFrame, name); + else + out.printf("%-3d %p", frameNumber, stackFrame); + } + + auto str = out.toCString(); + Bun__crashReportWrite(ctx, str.data(), str.length()); + }); }
\ No newline at end of file diff --git a/src/bun.js/module_loader.zig b/src/bun.js/module_loader.zig index 82e96c8ed..59a4288fb 100644 --- a/src/bun.js/module_loader.zig +++ b/src/bun.js/module_loader.zig @@ -1357,6 +1357,7 @@ pub const ModuleLoader = struct { if (err == error.AsyncModule) { unreachable; } + VirtualMachine.processFetchLog(globalObject, specifier.*, referrer.*, &log, ret, err); return true; }) |builtin| { diff --git a/src/crash_reporter.zig b/src/crash_reporter.zig new file mode 100644 index 000000000..4d98b47f4 --- /dev/null +++ b/src/crash_reporter.zig @@ -0,0 +1,50 @@ +const std = @import("std"); + +fn setup_sigactions(act: ?*const os.Sigaction) !void { + try os.sigaction(os.SIG.ABRT, act, null); + try os.sigaction(os.SIG.BUS, act, null); + try os.sigaction(os.SIG.FPE, act, null); + try os.sigaction(os.SIG.ILL, act, null); + try os.sigaction(os.SIG.SEGV, act, null); + try os.sigaction(os.SIG.TRAP, act, null); +} + +const builtin = @import("builtin"); +const ErrorCallback = fn (sig: i32, addr: usize) void; +var on_error: ?ErrorCallback = null; +noinline fn sigaction_handler(sig: i32, info: *const std.os.siginfo_t, _: ?*const anyopaque) callconv(.C) void { + // Prevent recursive calls + setup_sigactions(null) catch unreachable; + + const addr = switch (comptime builtin.target.os.tag) { + .linux => @ptrToInt(info.fields.sigfault.addr), + .macos, .freebsd => @ptrToInt(info.addr), + .netbsd => @ptrToInt(info.info.reason.fault.addr), + .openbsd => @ptrToInt(info.data.fault.addr), + .solaris => @ptrToInt(info.reason.fault.addr), + else => unreachable, + }; + if (on_error) |handle| handle(sig, addr); +} + +pub fn reloadHandlers() !void { + try setup_sigactions(null); + + var act = os.Sigaction{ + .handler = .{ .sigaction = sigaction_handler }, + .mask = os.empty_sigset, + .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), + }; + + try setup_sigactions(&act); +} +const os = std.os; +pub fn start() !void { + var act = os.Sigaction{ + .handler = .{ .sigaction = sigaction_handler }, + .mask = os.empty_sigset, + .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), + }; + + try setup_sigactions(&act); +} diff --git a/src/deps/backtrace.zig b/src/deps/backtrace.zig index 47293d1cf..e69de29bb 100644 --- a/src/deps/backtrace.zig +++ b/src/deps/backtrace.zig @@ -1,148 +0,0 @@ -const Environment = @import("../env.zig"); -pub const backtrace_state = struct_backtrace_state; -pub const struct_backtrace_state = opaque {}; -pub const backtrace_error_callback = ?fn ( - ?*anyopaque, - [*c]const u8, - c_int, -) callconv(.C) void; -pub extern fn backtrace_create_state( - filename: [*c]const u8, - threaded: c_int, - error_callback: backtrace_error_callback, - data: ?*anyopaque, -) ?*struct_backtrace_state; -pub const backtrace_full_callback = ?fn ( - ?*anyopaque, - usize, - [*c]const u8, - c_int, - [*c]const u8, -) callconv(.C) c_int; -pub extern fn backtrace_full( - state: ?*struct_backtrace_state, - skip: c_int, - callback: backtrace_full_callback, - error_callback: backtrace_error_callback, - data: ?*anyopaque, -) c_int; -pub const backtrace_simple_callback = ?fn (?*anyopaque, usize) callconv(.C) c_int; -pub extern fn backtrace_simple( - state: ?*struct_backtrace_state, - skip: c_int, - callback: backtrace_simple_callback, - error_callback: backtrace_error_callback, - data: ?*anyopaque, -) c_int; -pub extern fn backtrace_print(state: ?*struct_backtrace_state, skip: c_int, [*c]anyopaque) void; -pub extern fn backtrace_pcinfo( - state: ?*struct_backtrace_state, - pc: usize, - callback: backtrace_full_callback, - error_callback: backtrace_error_callback, - data: ?*anyopaque, -) c_int; -pub const backtrace_syminfo_callback = ?fn (?*anyopaque, usize, [*c]const u8, usize, usize) callconv(.C) void; -pub extern fn backtrace_syminfo( - state: ?*struct_backtrace_state, - addr: usize, - callback: backtrace_syminfo_callback, - error_callback: backtrace_error_callback, - data: ?*anyopaque, -) c_int; - -pub const BACKTRACE_SUPPORTED = @as(c_int, 1); -pub const BACKTRACE_USES_MALLOC = @as(c_int, 0); -pub const BACKTRACE_SUPPORTS_THREADS = @as(c_int, 1); -pub const BACKTRACE_SUPPORTS_DATA = @as(c_int, 1); - -fn error_callback(data: *anyopaque, msg: [*c]u8, errnum: c_int) callconv(.C) void { - _ = data; - _ = msg; - _ = errnum; -} - -pub const StackFrame = struct { - pc: usize, - filename: []const u8, - function_name: []const u8, - line_number: c_int, -}; - -pub const PrintCallback = fn (ctx: ?*anyopaque, frame: StackFrame) void; - -var callback: PrintCallback = undefined; -var callback_ctx: ?*anyopaque = null; - -const std = @import("std"); - -noinline fn full_callback(_: ?*anyopaque, pc: usize, filename: [*c]const u8, line_number: c_int, function_name: [*c]const u8) callconv(.C) c_int { - var stack_frame = StackFrame{ - .pc = pc, - .line_number = line_number, - .function_name = if (function_name) |fn_| std.mem.span(fn_) else "", - .filename = if (filename) |fn_| std.mem.span(fn_) else "", - }; - callback(callback_ctx, stack_frame); - return 0; -} - -var state: ?*backtrace_state = null; -pub inline fn print() void { - if (Environment.isMac) return; - state = backtrace_create_state(null, BACKTRACE_SUPPORTS_THREADS, null, null); - _ = backtrace_full(state, 2, full_callback, null, null); -} - -fn setup_sigactions(act: ?*const os.Sigaction) !void { - try os.sigaction(os.SIG.ABRT, act, null); - try os.sigaction(os.SIG.BUS, act, null); - try os.sigaction(os.SIG.FPE, act, null); - try os.sigaction(os.SIG.ILL, act, null); - try os.sigaction(os.SIG.SEGV, act, null); - try os.sigaction(os.SIG.TRAP, act, null); -} - -const builtin = @import("builtin"); -const ErrorCallback = fn (sig: i32, addr: usize) void; -var on_error: ?ErrorCallback = null; -noinline fn sigaction_handler(sig: i32, info: *const std.os.siginfo_t, _: ?*const anyopaque) callconv(.C) void { - // Prevent recursive calls - setup_sigactions(null) catch unreachable; - - const addr = switch (comptime builtin.target.os.tag) { - .linux => @ptrToInt(info.fields.sigfault.addr), - .macos, .freebsd => @ptrToInt(info.addr), - .netbsd => @ptrToInt(info.info.reason.fault.addr), - .openbsd => @ptrToInt(info.data.fault.addr), - .solaris => @ptrToInt(info.reason.fault.addr), - else => unreachable, - }; - if (on_error) |handle| handle(sig, addr); -} - -pub fn reloadHandlers() !void { - try setup_sigactions(null); - - var act = os.Sigaction{ - .handler = .{ .sigaction = sigaction_handler }, - .mask = os.empty_sigset, - .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), - }; - - try setup_sigactions(&act); -} -const os = std.os; -pub fn start(ctx: ?*anyopaque, callback_: PrintCallback, onError: ErrorCallback) !void { - callback_ctx = ctx; - callback = callback_; - on_error = onError; - - var act = os.Sigaction{ - .handler = .{ .sigaction = sigaction_handler }, - .mask = os.empty_sigset, - .flags = (os.SA.SIGINFO | os.SA.RESTART | os.SA.RESETHAND), - }; - - try setup_sigactions(&act); -} diff --git a/src/main.zig b/src/main.zig index 9d92942be..e7073328f 100644 --- a/src/main.zig +++ b/src/main.zig @@ -30,16 +30,12 @@ pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) nore MainPanicHandler.handle_panic(msg, error_return_trace); } -const CrashReporter = @import("crash_reporter"); - -pub fn PLCrashReportHandler() void { - Report.fatal(null, null); -} +const CrashReporter = @import("./crash_reporter.zig"); pub var start_time: i128 = 0; pub fn main() void { if (comptime Environment.isRelease) - CrashReporter.start(null, Report.CrashReportWriter.printFrame, Report.handleCrash) catch unreachable; + CrashReporter.start(null) catch unreachable; start_time = std.time.nanoTimestamp(); diff --git a/src/report.zig b/src/report.zig index a39734a9d..8037c2899 100644 --- a/src/report.zig +++ b/src/report.zig @@ -15,7 +15,7 @@ const CLI = @import("./cli.zig").Cli; const Features = @import("./analytics/analytics_thread.zig").Features; const Platform = @import("./analytics/analytics_thread.zig").GenerateHeader.GeneratePlatform; const HTTP = @import("http").AsyncHTTP; -const CrashReporter = @import("crash_reporter"); +const CrashReporter = @import("./crash_reporter.zig"); const Report = @This(); @@ -230,7 +230,11 @@ pub fn fatal(err_: ?anyerror, msg_: ?string) void { // It only is a real crash report if it's not coming from Zig - CrashReportWriter.dump(); + if (comptime !@import("javascript_core").is_bindgen) { + std.mem.doNotOptimizeAway(&Bun__crashReportWrite); + Bun__crashReportDumpStackTrace(&crash_report_writer); + } + crash_report_writer.flush(); crash_report_writer.printPath(); @@ -244,6 +248,13 @@ pub fn fatal(err_: ?anyerror, msg_: ?string) void { var globalError_ranOnce = false; +export fn Bun__crashReportWrite(ctx: *CrashReportWriter, bytes_ptr: [*]const u8, len: usize) void { + if (len > 0) + ctx.print("{s}\n", .{bytes_ptr[0..len]}); +} + +extern "C" fn Bun__crashReportDumpStackTrace(ctx: *anyopaque) void; + pub noinline fn handleCrash(signal: i32, addr: usize) void { const had_printed_fatal = has_printed_fatal; if (has_printed_fatal) return; @@ -263,7 +274,10 @@ pub noinline fn handleCrash(signal: i32, addr: usize) void { .{ @errorName(name), std.fmt.fmtSliceHexUpper(std.mem.asBytes(&addr)) }, ); printMetadata(); - CrashReportWriter.dump(); + if (comptime !@import("javascript_core").is_bindgen) { + std.mem.doNotOptimizeAway(&Bun__crashReportWrite); + Bun__crashReportDumpStackTrace(&crash_report_writer); + } if (!had_printed_fatal) { crash_report_writer.print("\nAsk for #help in https://bun.sh/discord or go to https://bun.sh/issues\n\n", .{}); |