mirror of
https://github.com/oven-sh/bun
synced 2026-02-13 12:29:07 +00:00
partial fix for the sendfile() bug
This commit is contained in:
@@ -769,29 +769,41 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
return this.onSendfile();
|
||||
}
|
||||
|
||||
pub fn onPrepareSendfileWrap(this: *anyopaque, fd: i32, size: anyerror!Blob.SizeType, _: *JSGlobalObject) void {
|
||||
onPrepareSendfile(bun.cast(*RequestContext, this), fd, size);
|
||||
pub fn onPrepareSendfileWrap(this: *anyopaque, fd: i32, size: Blob.SizeType, err: ?JSC.SystemError, globalThis: *JSGlobalObject) void {
|
||||
onPrepareSendfile(bun.cast(*RequestContext, this), fd, size, err, globalThis);
|
||||
}
|
||||
|
||||
fn onPrepareSendfile(this: *RequestContext, fd: i32, size: anyerror!Blob.SizeType) void {
|
||||
fn onPrepareSendfile(this: *RequestContext, fd: i32, size: Blob.SizeType, err: ?JSC.SystemError, globalThis: *JSGlobalObject) void {
|
||||
this.setAbortHandler();
|
||||
if (this.aborted) return;
|
||||
const size_ = size catch {
|
||||
this.req.setYield(true);
|
||||
this.finalize();
|
||||
|
||||
if (err) |system_error| {
|
||||
if (system_error.errno == @enumToInt(std.os.E.NOENT)) {
|
||||
this.runErrorHandlerWithStatusCode(system_error.toErrorInstance(globalThis), 404);
|
||||
} else {
|
||||
this.runErrorHandlerWithStatusCode(system_error.toErrorInstance(globalThis), 500);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
this.blob.size = size_;
|
||||
}
|
||||
|
||||
this.blob.size = size;
|
||||
this.needs_content_length = true;
|
||||
|
||||
this.sendfile = .{
|
||||
.fd = fd,
|
||||
.remain = size_,
|
||||
.socket_fd = this.resp.getNativeHandle(),
|
||||
.remain = size,
|
||||
.socket_fd = if (!this.aborted) this.resp.getNativeHandle() else -999,
|
||||
};
|
||||
|
||||
if (this.aborted) {
|
||||
_ = JSC.Node.Syscall.close(this.sendfile.fd);
|
||||
this.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
this.resp.runCorked(*RequestContext, renderMetadata, this);
|
||||
|
||||
if (size_ == 0) {
|
||||
if (size == 0) {
|
||||
this.cleanupAfterSendfile();
|
||||
this.finalize();
|
||||
|
||||
@@ -900,15 +912,34 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
this.doRenderWithBody(&response.body.value);
|
||||
}
|
||||
|
||||
pub fn renderProductionError(this: *RequestContext) void {
|
||||
this.resp.writeStatus("500 Internal Server Error");
|
||||
this.resp.writeHeader("content-type", "text/plain");
|
||||
this.resp.end("Something went wrong!", true);
|
||||
pub fn renderProductionError(this: *RequestContext, status: u16) void {
|
||||
switch (status) {
|
||||
404 => {
|
||||
this.resp.writeStatus("404 Not Found");
|
||||
this.resp.endWithoutBody();
|
||||
},
|
||||
else => {
|
||||
this.resp.writeStatus("500 Internal Server Error");
|
||||
this.resp.writeHeader("content-type", "text/plain");
|
||||
this.resp.end("Something went wrong!", true);
|
||||
},
|
||||
}
|
||||
|
||||
this.finalize();
|
||||
}
|
||||
|
||||
pub fn runErrorHandler(this: *RequestContext, value: JSC.JSValue) void {
|
||||
pub fn runErrorHandler(
|
||||
this: *RequestContext,
|
||||
value: JSC.JSValue,
|
||||
) void {
|
||||
runErrorHandlerWithStatusCode(this, value, 500);
|
||||
}
|
||||
|
||||
pub fn runErrorHandlerWithStatusCode(
|
||||
this: *RequestContext,
|
||||
value: JSC.JSValue,
|
||||
status: u16,
|
||||
) void {
|
||||
if (this.resp.hasResponded()) return;
|
||||
|
||||
var exception_list: std.ArrayList(Api.JsException) = std.ArrayList(Api.JsException).init(bun.default_allocator);
|
||||
@@ -919,10 +950,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
const result = JSC.C.JSObjectCallAsFunctionReturnValue(this.server.globalThis.ref(), this.server.config.onError.asObjectRef(), null, 1, &args);
|
||||
|
||||
if (!result.isEmptyOrUndefinedOrNull()) {
|
||||
JSC.C.JSValueProtect(this.server.globalThis.ref(), result.asObjectRef());
|
||||
if (result.isError() or result.isAggregateError(this.server.globalThis)) {
|
||||
this.runErrorHandler(result);
|
||||
JSC.C.JSValueUnprotect(this.server.globalThis.ref(), result.asObjectRef());
|
||||
return;
|
||||
} else if (result.as(Response)) |response| {
|
||||
this.render(response);
|
||||
@@ -942,8 +971,9 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
.{ std.mem.span(@tagName(this.method)), this.url },
|
||||
);
|
||||
} else {
|
||||
JSC.VirtualMachine.vm.defaultErrorHandler(value, &exception_list);
|
||||
this.renderProductionError();
|
||||
if (status != 404)
|
||||
JSC.VirtualMachine.vm.defaultErrorHandler(value, &exception_list);
|
||||
this.renderProductionError(status);
|
||||
}
|
||||
JSC.VirtualMachine.vm.log.reset();
|
||||
return;
|
||||
|
||||
@@ -1714,7 +1714,8 @@ pub const Blob = struct {
|
||||
pub const OnCompleteCallback = fn (
|
||||
ctx: *anyopaque,
|
||||
fd: JSC.Node.FileDescriptor,
|
||||
size: anyerror!SizeType,
|
||||
size: SizeType,
|
||||
system_error: ?SystemError,
|
||||
global: *JSGlobalObject,
|
||||
) void;
|
||||
|
||||
@@ -1759,15 +1760,16 @@ pub const Blob = struct {
|
||||
var cb_ctx = this.onCompleteCtx;
|
||||
const fd = this.opened_fd;
|
||||
const _size = this.size;
|
||||
const errno = this.errno;
|
||||
this.store.deref();
|
||||
const system_error_ = this.system_error;
|
||||
var store = this.store;
|
||||
|
||||
bun.default_allocator.destroy(this);
|
||||
if (errno) |err| {
|
||||
cb(cb_ctx, fd, err, globalThis);
|
||||
if (system_error_) |err| {
|
||||
cb(cb_ctx, -1, 0, err, globalThis);
|
||||
} else {
|
||||
cb(cb_ctx, fd, _size, globalThis);
|
||||
cb(cb_ctx, fd, _size, null, globalThis);
|
||||
}
|
||||
store.deref();
|
||||
}
|
||||
|
||||
fn _runAsync(this: *OpenAndStatFile) void {
|
||||
@@ -1785,6 +1787,7 @@ pub const Blob = struct {
|
||||
.result => |result| result,
|
||||
.err => |err| {
|
||||
this.errno = AsyncIO.asError(err.errno);
|
||||
this.system_error = err.toSystemError();
|
||||
return;
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user