diff options
author | 2021-09-16 18:27:54 -0700 | |
---|---|---|
committer | 2021-09-16 18:27:54 -0700 | |
commit | 6352e95d0f9ff168f148dfa100b172f59f1ab6ff (patch) | |
tree | d6ac6f925834a3636f32c8d54312f5af28515fd1 | |
parent | b6a72f7d727c2465071b0f74c1c3ef0df1691dfb (diff) | |
download | bun-6352e95d0f9ff168f148dfa100b172f59f1ab6ff.tar.gz bun-6352e95d0f9ff168f148dfa100b172f59f1ab6ff.tar.zst bun-6352e95d0f9ff168f148dfa100b172f59f1ab6ff.zip |
When port is in use, auto-increment port number up to 10 times and then bail if all 10 are in use
-rw-r--r-- | src/http.zig | 50 |
1 files changed, 43 insertions, 7 deletions
diff --git a/src/http.zig b/src/http.zig index 93deb5556..4e0d50e1f 100644 --- a/src/http.zig +++ b/src/http.zig @@ -2525,14 +2525,14 @@ pub const Server = struct { fn run(server: *Server, comptime features: ConnectionFeatures) !void { adjustUlimit() catch {}; - const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); - defer listener.deinit(); RequestContext.WebsocketHandler.open_websockets = @TypeOf( RequestContext.WebsocketHandler.open_websockets, ).init(server.allocator); + const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); + defer listener.deinit(); listener.setReuseAddress(true) catch {}; - listener.setReusePort(true) catch {}; + listener.setReusePort(false) catch {}; listener.setFastOpen(true) catch {}; // listener.setNoDelay(true) catch {}; // listener.setQuickACK(true) catch {}; @@ -2545,10 +2545,46 @@ pub const Server = struct { port = _port; } - try listener.bind(ip.Address.initIPv4( - IPv4.unspecified, - port, - )); + { + var attempts: u8 = 0; + + restart: while (attempts < 10) : (attempts += 1) { + listener.bind(ip.Address.initIPv4( + IPv4.unspecified, + port, + )) catch |err| { + switch (err) { + error.AddressInUse => { + port += 1; + continue :restart; + }, + else => { + Output.prettyErrorln("<r><red>{s} while trying to start listening on port {d}.\n\n", .{ @errorName(err), port }); + Output.flush(); + std.os.exit(1); + }, + } + }; + break :restart; + } + + if (attempts >= 10) { + var random_number = std.rand.DefaultPrng.init(@intCast(u64, std.time.milliTimestamp())); + const default_port = @intCast(u16, server.bundler.options.origin.getPort() orelse 3000); + Output.prettyErrorln( + "<r><red>error<r>: Bun can't start because <b>port {d} is already in use<r>. Tried {d} - {d}. Try closing the other apps or manually passing Bun a port\n\n <r><cyan><b>bun --origin http://localhost:{d}/<r>\n", + .{ + default_port, + default_port, + port, + random_number.random.intRangeAtMost(u16, 3011, 65535), + }, + ); + Output.flush(); + std.os.exit(1); + } + } + try listener.listen(1280); const addr = try listener.getLocalAddress(); if (server.bundler.options.origin.getPort()) |_port| { |