aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-01-04 18:29:21 -0800
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-01-04 18:29:21 -0800
commit0edf6fd1e4fed378328ef58c0d872631efc9e9d1 (patch)
treec909140a08e2a4c12a634ef5d06f184aa1f8f3b0 /src
parentc9d6c25f710e274383d10532aad6671e5cde4249 (diff)
downloadbun-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/analytics/analytics_thread.zig5
-rw-r--r--src/bundler.zig6
-rw-r--r--src/main.zig53
-rw-r--r--src/report.zig240
4 files changed, 247 insertions, 57 deletions
diff --git a/src/analytics/analytics_thread.zig b/src/analytics/analytics_thread.zig
index 026947445..e883a798f 100644
--- a/src/analytics/analytics_thread.zig
+++ b/src/analytics/analytics_thread.zig
@@ -375,7 +375,10 @@ fn start() bool {
fn spawn() !void {
@setCold(true);
has_loaded = true;
- thread = try std.Thread.spawn(.{}, readloop, .{});
+ thread = std.Thread.spawn(.{}, readloop, .{}) catch {
+ disabled = true;
+ return;
+ };
}
const headers_buf: string = "Content-Type binary/peechy";
diff --git a/src/bundler.zig b/src/bundler.zig
index 5afd25d6a..5dcff1292 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -49,7 +49,7 @@ const NodeFallbackModules = @import("./node_fallbacks.zig");
const CacheEntry = @import("./cache.zig").FsCacheEntry;
const Analytics = @import("./analytics/analytics_thread.zig");
const URL = @import("./query_string_map.zig").URL;
-
+const Report = @import("./report.zig");
const Linker = linker.Linker;
const Resolver = _resolver.Resolver;
@@ -603,9 +603,7 @@ pub const Bundler = struct {
Output.flush();
}
- this.loop() catch |err| {
- Output.prettyErrorln("<r><red>Error: {s}<r>", .{@errorName(err)});
- };
+ this.loop() catch |err| Report.globalError(err);
}
pub fn loop(this: *Worker) anyerror!void {
diff --git a/src/main.zig b/src/main.zig
index 4da55d864..b3455d884 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -54,58 +54,7 @@ pub fn main() anyerror!void {
Output.Source.set(&output_source);
defer Output.flush();
- cli.Cli.start(default_allocator, stdout, stderr, MainPanicHandler) catch |err| {
- 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.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);
- },
- }
- };
+ cli.Cli.start(default_allocator, stdout, stderr, MainPanicHandler) catch |err| Report.globalError(err);
std.mem.doNotOptimizeAway(JavaScriptVirtualMachine.fetch);
std.mem.doNotOptimizeAway(JavaScriptVirtualMachine.init);
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);
+}