aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile24
-rw-r--r--src/http.zig87
-rw-r--r--src/io/io_darwin.zig2
-rw-r--r--src/javascript/jsc/node/syscall.zig46
4 files changed, 116 insertions, 43 deletions
diff --git a/Makefile b/Makefile
index d79a06dac..8f4e85631 100644
--- a/Makefile
+++ b/Makefile
@@ -61,11 +61,11 @@ CC = $(shell which clang-13 || which clang)
CXX = $(shell which clang++-13 || which clang++)
ifeq ($(OS_NAME),darwin)
-# LLVM_PREFIX = $(shell brew --prefix llvm)
-# LDFLAGS += " -L$(LLVM_PREFIX)/lib"
-# CPPFLAGS += " -I$(LLVM_PREFIX)/include"
-CC = /usr/bin/clang
-CXX = /usr/bin/clang++
+LLVM_PREFIX = $(shell brew --prefix llvm)
+LDFLAGS += " -L$(LLVM_PREFIX)/lib"
+CPPFLAGS += " -I$(LLVM_PREFIX)/include"
+CC = $(LLVM_PREFIX)/bin/clang
+CXX = $(LLVM_PREFIX)/bin/clang++
CODESIGN_IDENTITY ?= $(shell security find-identity -v -p codesigning | awk '/Apple Development/ { print $$2 }')
endif
@@ -948,19 +948,21 @@ jsc-bindings-mac: $(OBJ_FILES) $(WEBCORE_OBJ_FILES)
mimalloc-debug:
rm -rf $(BUN_DEPS_DIR)/mimalloc/CMakeCache* $(BUN_DEPS_DIR)/mimalloc/CMakeFiles
cd $(BUN_DEPS_DIR)/mimalloc; make clean || echo ""; \
- CFLAGS="$(CFLAGS)" cmake $(CMAKE_FLAGS_WITHOUT_RELEASE) \
+ CFLAGS="$(CFLAGS)" cmake $(CMAKE_FLAGS_WITHOUT_RELEASE) ${MIMALLOC_OVERRIDE_FLAG} \
-DCMAKE_BUILD_TYPE=Debug \
-DMI_DEBUG_FULL=1 \
-DMI_SKIP_COLLECT_ON_EXIT=1 \
-DMI_BUILD_SHARED=OFF \
-DMI_BUILD_STATIC=ON \
-DMI_BUILD_TESTS=OFF \
- -DMI_BUILD_OBJECT=ON \
- -DMI_BUILD_OBJECT=ON \
-DMI_OSX_ZONE=OFF \
-DMI_OSX_INTERPOSE=OFF \
- ${MIMALLOC_OVERRIDE_FLAG} \
- -DMI_USE_CXX=OFF .\
+ -DMI_BUILD_OBJECT=ON \
+ -DMI_USE_CXX=ON \
+ -DMI_OVERRIDE=OFF \
+ -DCMAKE_C_FLAGS="$(CFLAGS)" \
+ -DCMAKE_CXX_FLAGS="$(CFLAGS)" \
+ . \
&& make -j $(CPUS);
cp $(BUN_DEPS_DIR)/mimalloc/$(_MIMALLOC_DEBUG_FILE) $(BUN_DEPS_OUT_DIR)/$(MIMALLOC_FILE)
@@ -980,7 +982,7 @@ mimalloc:
-DMI_OSX_INTERPOSE=OFF \
-DMI_BUILD_OBJECT=ON \
-DMI_USE_CXX=ON \
- -DMI_OVERRIDE=ON \
+ -DMI_OVERRIDE=OFF \
-DCMAKE_C_FLAGS="$(CFLAGS)" \
-DCMAKE_CXX_FLAGS="$(CFLAGS)" \
${MIMALLOC_OVERRIDE_FLAG} \
diff --git a/src/http.zig b/src/http.zig
index 973b0532f..430a72a6e 100644
--- a/src/http.zig
+++ b/src/http.zig
@@ -73,6 +73,7 @@ threadlocal var res_headers_buf: [100]picohttp.Header = undefined;
const sync = @import("./sync.zig");
const JavaScript = @import("javascript_core");
const JavaScriptCore = JavaScriptCore.C;
+const Syscall = JavaScript.Node.Syscall;
const Router = @import("./router.zig");
pub const Watcher = watcher.NewWatcher(*Server);
const ZigURL = @import("./url.zig").URL;
@@ -663,18 +664,29 @@ pub const RequestContext = struct {
_ = try ctx.writeSocket(writer.getWritten(), SOCKET_FLAGS);
}
+ const AsyncIO = @import("io");
pub fn writeSocket(ctx: *RequestContext, buf: anytype, _: anytype) !usize {
// ctx.conn.client.setWriteBufferSize(@intCast(u32, buf.len)) catch {};
- const written = ctx.conn.client.write(buf, SOCKET_FLAGS) catch |err| {
- Output.printError("Write error: {s}", .{@errorName(err)});
- return err;
- };
- if (written == 0) {
- return error.SocketClosed;
- }
+ switch (Syscall.send(ctx.conn.client.socket.fd, buf, SOCKET_FLAGS)) {
+ .err => |err| {
+ const erro = AsyncIO.asError(err.getErrno());
+ if (erro == error.EBADF or erro == error.ECONNABORTED or erro == error.ECONNREFUSED) {
+ return error.SocketClosed;
+ }
+
+ Output.prettyErrorln("send() error: {s}", .{err.toSystemError().message.slice()});
+
+ return erro;
+ },
+ .result => |written| {
+ if (written == 0) {
+ return error.SocketClosed;
+ }
- return written;
+ return written;
+ },
+ }
}
pub fn writeBodyBuf(ctx: *RequestContext, body: []const u8) !void {
@@ -707,14 +719,15 @@ pub const RequestContext = struct {
}
pub fn init(
+ this: *RequestContext,
req: Request,
arena: ThreadlocalArena,
conn: *tcp.Connection,
bundler_: *Bundler,
watcher_: *Watcher,
timer: std.time.Timer,
- ) !RequestContext {
- var ctx = RequestContext{
+ ) !void {
+ this.* = RequestContext{
.request = req,
.arena = arena,
.bundler = bundler_,
@@ -727,8 +740,6 @@ pub const RequestContext = struct {
.timer = timer,
.origin = bundler_.options.origin,
};
-
- return ctx;
}
// not all browsers send this
@@ -1676,8 +1687,8 @@ pub const RequestContext = struct {
clone.websocket = Websocket.Websocket.create(&clone.conn, SOCKET_FLAGS);
clone.tombstone = false;
- clone.ctx.allocator = undefined;
- clone.ctx.arena.deinit();
+ ctx.allocator = undefined;
+ ctx.arena.deinit();
try open_websockets.append(clone);
return clone;
@@ -1771,25 +1782,27 @@ pub const RequestContext = struct {
websocket_printer,
);
- _handle(self) catch {};
- }
+ self.ctx.arena = ThreadlocalArena.init() catch unreachable;
+ self.ctx.allocator = self.ctx.arena.allocator();
+ self.builder.bundler.resolver.caches = CacheSet.init(self.ctx.allocator);
+ self.builder.bundler.resolver.caches.fs.stream = true;
- fn _handle(handler: *WebsocketHandler) !void {
- var ctx = &handler.ctx;
- ctx.arena = ThreadlocalArena.init() catch unreachable;
- ctx.allocator = ctx.arena.allocator();
- handler.builder.bundler.resolver.caches = CacheSet.init(ctx.allocator);
- handler.builder.bundler.resolver.caches.fs.stream = true;
+ _handle(self, &self.ctx) catch {};
+ }
+ fn _handle(handler: *WebsocketHandler, ctx: *RequestContext) !void {
var is_socket_closed = false;
+ const fd = ctx.conn.client.socket.fd;
defer {
websocket_printer = handler.builder.printer.ctx;
handler.tombstone = true;
removeWebsocket(handler);
+
ctx.arena.deinit();
if (!is_socket_closed) {
- ctx.conn.deinit();
+ _ = Syscall.close(fd);
}
+ bun.default_allocator.destroy(handler);
Output.flush();
}
@@ -1826,8 +1839,20 @@ pub const RequestContext = struct {
ctx.appendHeader("Upgrade", "websocket");
ctx.appendHeader("Sec-WebSocket-Accept", key);
ctx.appendHeader("Sec-WebSocket-Protocol", "bun-hmr");
- try ctx.writeStatus(101);
- try ctx.flushHeaders();
+ ctx.writeStatus(101) catch |err| {
+ if (err == error.SocketClosed) {
+ is_socket_closed = true;
+ }
+
+ return;
+ };
+ ctx.flushHeaders() catch |err| {
+ if (err == error.SocketClosed) {
+ is_socket_closed = true;
+ }
+
+ return;
+ };
// Output.prettyErrorln("<r><green>101<r><d> Hot Module Reloading connected.<r>", .{});
// Output.flush();
Analytics.Features.hot_module_reloading = true;
@@ -3656,14 +3681,16 @@ pub const Server = struct {
var req = picohttp.Request.parse(req_buf_node.data[0..read_size], &req_headers_buf) catch |err| {
_ = conn.client.write(RequestContext.printStatusLine(400) ++ "\r\n\r\n", SOCKET_FLAGS) catch {};
- conn.client.deinit();
+ _ = Syscall.close(conn.client.socket.fd);
Output.printErrorln("ERR: {s}", .{@errorName(err)});
return;
};
var request_arena = ThreadlocalArena.init() catch unreachable;
+ var request_allocator = request_arena.allocator();
+ var req_ctx = request_allocator.create(RequestContext) catch unreachable;
- req_ctx_ = RequestContext.init(
+ req_ctx.init(
req,
request_arena,
conn,
@@ -3672,15 +3699,15 @@ pub const Server = struct {
server.timer,
) catch |err| {
Output.prettyErrorln("<r>[<red>{s}<r>] - <b>{s}<r>: {s}", .{ @errorName(err), req.method, req.path });
- conn.client.deinit();
+ _ = Syscall.close(conn.client.socket.fd);
+ request_arena.deinit();
return;
};
- var req_ctx = &req_ctx_;
req_ctx.req_body_node = req_buf_node;
req_ctx.timer.reset();
- const is_navigation_request = req_ctx_.isBrowserNavigation();
+ const is_navigation_request = req_ctx.isBrowserNavigation();
defer if (is_navigation_request == .yes) Analytics.enqueue(Analytics.EventName.http_build);
req_ctx.parseOrigin();
// req_ctx.appendHeader("Date", value: string)
diff --git a/src/io/io_darwin.zig b/src/io/io_darwin.zig
index c3175a0ed..b399ce62f 100644
--- a/src/io/io_darwin.zig
+++ b/src/io/io_darwin.zig
@@ -259,7 +259,7 @@ const fd_t = os.fd_t;
const mem = std.mem;
const assert = std.debug.assert;
const c = std.c;
-const darwin = struct {
+pub const darwin = struct {
pub usingnamespace os.darwin;
pub extern "c" fn @"recvfrom$NOCANCEL"(sockfd: c.fd_t, noalias buf: *anyopaque, len: usize, flags: u32, noalias src_addr: ?*c.sockaddr, noalias addrlen: ?*c.socklen_t) isize;
pub extern "c" fn @"sendto$NOCANCEL"(sockfd: c.fd_t, buf: *const anyopaque, len: usize, flags: u32, dest_addr: ?*const c.sockaddr, addrlen: c.socklen_t) isize;
diff --git a/src/javascript/jsc/node/syscall.zig b/src/javascript/jsc/node/syscall.zig
index d51062a83..cd7a56157 100644
--- a/src/javascript/jsc/node/syscall.zig
+++ b/src/javascript/jsc/node/syscall.zig
@@ -17,7 +17,7 @@ const C = @import("../../../global.zig").C;
const linux = os.linux;
const Maybe = JSC.Node.Maybe;
-pub const system = if (Environment.isLinux) linux else darwin;
+pub const system = if (Environment.isLinux) linux else @import("io").darwin;
pub const S = struct {
pub usingnamespace if (Environment.isLinux) linux.S else std.os.S;
};
@@ -88,6 +88,8 @@ pub const Tag = enum(u8) {
getcwd,
chdir,
fcopyfile,
+ recv,
+ send,
pub var strings = std.EnumMap(Tag, JSC.C.JSStringRef).initFull(null);
};
@@ -273,6 +275,48 @@ pub fn read(fd: os.fd_t, buf: []u8) Maybe(usize) {
unreachable;
}
+pub fn recv(fd: os.fd_t, buf: []u8, flag: u32) Maybe(usize) {
+ if (comptime Environment.isMac) {
+ const rc = system.@"recvfrom$NOCANCEL"(fd, buf.ptr, bun.len, flag, null, null);
+ if (Maybe(usize).errnoSys(rc, .recv)) |err| {
+ return err;
+ }
+ return Maybe(usize){ .result = @intCast(usize, rc) };
+ } else {
+ while (true) {
+ const rc = linux.recvfrom(fd, buf.ptr, bun.len, flag | os.SOCK.CLOEXEC | os.MSG.NOSIGNAL, null, null);
+ if (Maybe(usize).errnoSys(rc, .recv)) |err| {
+ if (err.getErrno() == .INTR) continue;
+ return err;
+ }
+ return Maybe(usize){ .result = @intCast(usize, rc) };
+ }
+ }
+ unreachable;
+}
+
+pub fn send(fd: os.fd_t, buf: []const u8, flag: u32) Maybe(usize) {
+ if (comptime Environment.isMac) {
+ const rc = system.@"sendto$NOCANCEL"(fd, buf.ptr, buf.len, flag, null, 0);
+ if (Maybe(usize).errnoSys(rc, .send)) |err| {
+ return err;
+ }
+ return Maybe(usize){ .result = @intCast(usize, rc) };
+ } else {
+ while (true) {
+ const rc = linux.sendto(fd, buf.ptr, buf.len, flag | os.SOCK.CLOEXEC | os.MSG.NOSIGNAL, null, 0);
+
+ if (Maybe(usize).errnoSys(rc, .send)) |err| {
+ if (err.getErrno() == .INTR) continue;
+ return err;
+ }
+
+ return Maybe(usize){ .result = @intCast(usize, rc) };
+ }
+ }
+ unreachable;
+}
+
pub fn readlink(in: [:0]const u8, buf: []u8) Maybe(usize) {
while (true) {
const rc = sys.readlink(in, buf.ptr, buf.len);