diff options
author | 2022-01-04 18:29:21 -0800 | |
---|---|---|
committer | 2022-01-04 18:29:21 -0800 | |
commit | 0edf6fd1e4fed378328ef58c0d872631efc9e9d1 (patch) | |
tree | c909140a08e2a4c12a634ef5d06f184aa1f8f3b0 /src/report.zig | |
parent | c9d6c25f710e274383d10532aad6671e5cde4249 (diff) | |
download | bun-0edf6fd1e4fed378328ef58c0d872631efc9e9d1.tar.gz bun-0edf6fd1e4fed378328ef58c0d872631efc9e9d1.tar.zst bun-0edf6fd1e4fed378328ef58c0d872631efc9e9d1.zip |
Improve error handling when out of file handles
Diffstat (limited to '')
-rw-r--r-- | src/report.zig | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/report.zig b/src/report.zig index 7032fc9aa..400a4dc41 100644 --- a/src/report.zig +++ b/src/report.zig @@ -16,6 +16,8 @@ const Features = @import("./analytics/analytics_thread.zig").Features; const HTTP = @import("http").AsyncHTTP; const CrashReporter = @import("crash_reporter"); +const Report = @This(); + var crash_reporter_path: [1024]u8 = undefined; pub fn printMetadata() void { @setCold(true); @@ -166,3 +168,241 @@ pub fn fatal(err_: ?anyerror, msg_: ?string) void { Output.flush(); } } + +var globalError_ranOnce = false; + +pub noinline fn globalError(err: anyerror) noreturn { + @setCold(true); + + if (@atomicRmw(bool, &globalError_ranOnce, .Xchg, true, .Monotonic)) { + std.os.exit(1); + } + + switch (err) { + error.CurrentWorkingDirectoryUnlinked => { + Output.prettyError( + "\n<r><red>error: <r>The current working directory was deleted, so that command didn't work. Please cd into a different directory and try again.", + .{}, + ); + Output.flush(); + std.os.exit(1); + }, + error.SystemFdQuotaExceeded => { + const limit = std.os.getrlimit(.NOFILE) catch std.mem.zeroes(std.os.rlimit); + if (comptime Environment.isMac) { + Output.prettyError( + \\ + \\<r><red>error<r>: Your computer ran out of file descriptors <d>(<red>SystemFdQuotaExceeded<r><d>)<r> + \\ + \\<d>Current limit: {d}<r> + \\ + \\To fix this, try running: + \\ + \\ <cyan>sudo launchctl limit maxfiles 2147483646<r> + \\ <cyan>ulimit -n 2147483646<r> + \\ + \\That will only work until you reboot. + \\ + , + .{ + limit.cur, + }, + ); + } else { + Output.prettyError( + \\ + \\<r><red>error<r>: Your computer ran out of file descriptors <d>(<red>SystemFdQuotaExceeded<r><d>)<r> + \\ + \\<d>Current limit: {d}<r> + \\ + \\To fix this, try running: + \\ + \\ <cyan>sudo echo -e "\nfs.file-max=2147483646\n" >> /etc/sysctl.conf<r> + \\ <cyan>sudo sysctl -p<r> + \\ <cyan>ulimit -n 2147483646<r> + \\ + , + .{ + limit.cur, + }, + ); + + if (std.os.getenv("USER")) |user| { + if (user.len > 0) { + Output.prettyError( + \\ + \\If that still doesn't work, you may need to add these lines to /etc/security/limits.conf: + \\ + \\ <cyan>{s} soft nofile 2147483646<r> + \\ <cyan>{s} hard nofile 2147483646<r> + \\ + , + .{ user, user }, + ); + } + } + } + + Output.flush(); + std.os.exit(1); + }, + error.ProcessFdQuotaExceeded => { + const limit = std.os.getrlimit(.NOFILE) catch std.mem.zeroes(std.os.rlimit); + if (comptime Environment.isMac) { + Output.prettyError( + \\ + \\<r><red>error<r>: bun ran out of file descriptors <d>(<red>ProcessFdQuotaExceeded<r><d>)<r> + \\ + \\<d>Current limit: {d}<r> + \\ + \\To fix this, try running: + \\ + \\ <cyan>ulimit -n 2147483646<r> + \\ + \\You may also need to run: + \\ + \\ <cyan>sudo launchctl limit maxfiles 2147483646<r> + \\ + , + .{ + limit.cur, + }, + ); + } else { + Output.prettyError( + \\ + \\<r><red>error<r>: bun ran out of file descriptors <d>(<red>ProcessFdQuotaExceeded<r><d>)<r> + \\ + \\<d>Current limit: {d}<r> + \\ + \\To fix this, try running: + \\ + \\ <cyan>ulimit -n 2147483646<r> + \\ + \\That will only work for the current shell. To fix this for the entire system, run: + \\ + \\ <cyan>sudo echo -e "\nfs.file-max=2147483646\n" >> /etc/sysctl.conf<r> + \\ <cyan>sudo sysctl -p<r> + \\ + , + .{ + limit.cur, + }, + ); + + if (std.os.getenv("USER")) |user| { + if (user.len > 0) { + Output.prettyError( + \\ + \\If that still doesn't work, you may need to add these lines to /etc/security/limits.conf: + \\ + \\ <cyan>{s} soft nofile 2147483646<r> + \\ <cyan>{s} hard nofile 2147483646<r> + \\ + , + .{ user, user }, + ); + } + } + } + + Output.flush(); + std.os.exit(1); + }, + // The usage of `unreachable` in Zig's std.os may cause the file descriptor problem to show up as other errors + error.NotOpenForReading, error.Unexpected => { + const limit = std.os.getrlimit(.NOFILE) catch std.mem.zeroes(std.os.rlimit); + + if (limit.cur > 0 and limit.cur < (8096 * 2)) { + Output.prettyError( + \\ + \\<r><red>error<r>: An unknown error ocurred, possibly due to low max file descriptors <d>(<red>Unexpected<r><d>)<r> + \\ + \\<d>Current limit: {d}<r> + \\ + \\To fix this, try running: + \\ + \\ <cyan>ulimit -n 2147483646<r> + \\ + , + .{ + limit.cur, + }, + ); + + if (Environment.isLinux) { + if (std.os.getenv("USER")) |user| { + if (user.len > 0) { + Output.prettyError( + \\ + \\If that still doesn't work, you may need to add these lines to /etc/security/limits.conf: + \\ + \\ <cyan>{s} soft nofile 2147483646<r> + \\ <cyan>{s} hard nofile 2147483646<r> + \\ + , + .{ + user, + user, + }, + ); + } + } + } else if (Environment.isMac) { + Output.prettyError( + \\ + \\If that still doesn't work, you may need to run: + \\ + \\ <cyan>sudo launchctl limit maxfiles 2147483646<r> + \\ + , + .{}, + ); + } + + Output.flush(); + std.os.exit(1); + } + }, + error.FileNotFound => { + Output.prettyError( + "\n<r><red>error<r><d>:<r> <b>FileNotFound<r>\nbun could not find a file, and the code that produces this error is missing a better error.\n", + .{}, + ); + Output.flush(); + + Report.printMetadata(); + + Output.flush(); + + print_stacktrace: { + var debug_info = std.debug.getSelfDebugInfo() catch break :print_stacktrace; + var trace = @errorReturnTrace() orelse break :print_stacktrace; + Output.disableBuffering(); + std.debug.writeStackTrace(trace.*, Output.errorWriter(), default_allocator, debug_info, std.debug.detectTTYConfig()) catch break :print_stacktrace; + } + + std.os.exit(1); + }, + error.MissingPackageJSON => { + Output.prettyError( + "\n<r><red>error<r><d>:<r> <b>MissingPackageJSON<r>\nbun could not find a package.json file.\n", + .{}, + ); + Output.flush(); + std.os.exit(1); + }, + else => {}, + } + + Report.fatal(err, null); + + print_stacktrace: { + var debug_info = std.debug.getSelfDebugInfo() catch break :print_stacktrace; + var trace = @errorReturnTrace() orelse break :print_stacktrace; + Output.disableBuffering(); + std.debug.writeStackTrace(trace.*, Output.errorWriter(), default_allocator, debug_info, std.debug.detectTTYConfig()) catch break :print_stacktrace; + } + + std.os.exit(1); +} |