From 7c5ebbf8730ea90e32bea3f6c3ab87c6c246dfdf Mon Sep 17 00:00:00 2001 From: Benoit Giannangeli Date: Sat, 25 May 2024 12:17:26 +0200 Subject: [PATCH] fix(http): Prevent using http client or request once its collected FIXME: it seems http client won't allow being collected if all opened connection or pending request are not resolved. This means that our http client must keep track of all opened request and try to collect them first --- src/Parser.zig | 14 +++++++------- src/lib/buffer.buzz | 1 - src/lib/buzz_http.zig | 1 - src/lib/http.buzz | 21 ++++++++++++++++++--- src/memory.zig | 4 ++-- src/obj.zig | 8 +------- src/value.zig | 1 + tests/manual/006-http-client.buzz | 1 - 8 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/Parser.zig b/src/Parser.zig index e862a224..20abef5f 100644 --- a/src/Parser.zig +++ b/src/Parser.zig @@ -5637,11 +5637,6 @@ fn range(self: *Self, _: bool, low: Ast.Node.Index) Error!Ast.Node.Index { self.markInitialized(); - const list_def = obj.ObjList.ListDef.init(self.gc.allocator, self.gc.type_registry.int_type); - const resolved_type = obj.ObjTypeDef.TypeUnion{ - .List = list_def, - }; - return try self.ast.appendNode( .{ .tag = .Range, @@ -5651,7 +5646,12 @@ fn range(self: *Self, _: bool, low: Ast.Node.Index) Error!Ast.Node.Index { .{ .optional = false, .def_type = .Range, - .resolved_type = resolved_type, + .resolved_type = .{ + .List = obj.ObjList.ListDef.init( + self.gc.allocator, + self.gc.type_registry.int_type, + ), + }, }, ), .components = .{ @@ -6725,7 +6725,7 @@ fn enumDeclaration(self: *Self) Error!Ast.Node.Index { // Generate the enum constant var @"enum" = try self.gc.allocateObject( obj.ObjEnum, - obj.ObjEnum.init(self.gc.allocator, enum_type), + obj.ObjEnum.init(enum_type), ); var obj_cases = std.ArrayList(Value).init(self.gc.allocator); diff --git a/src/lib/buffer.buzz b/src/lib/buffer.buzz index 4552f60a..4cc64c29 100644 --- a/src/lib/buffer.buzz +++ b/src/lib/buffer.buzz @@ -1,7 +1,6 @@ namespace buffer; import "ffi"; -import "std"; export object WriteWhileReadingError {} export object OutOfBoundError {} diff --git a/src/lib/buzz_http.zig b/src/lib/buzz_http.zig index 964ed049..e15256f2 100644 --- a/src/lib/buzz_http.zig +++ b/src/lib/buzz_http.zig @@ -155,7 +155,6 @@ pub export fn HttpRequestDeinit(ctx: *api.NativeCtx) c_int { ), ); - api.VM.allocator.free(request.response.parser.header_bytes_buffer); request.deinit(); api.VM.allocator.destroy(request); diff --git a/src/lib/http.buzz b/src/lib/http.buzz index 6d2cb52c..3f57231c 100644 --- a/src/lib/http.buzz +++ b/src/lib/http.buzz @@ -1,6 +1,5 @@ namespace http; -import "std"; import "buffer"; import "errors"; @@ -46,6 +45,8 @@ export enum HttpError { UnsupportedTransferEncoding, UnsupportedUriScheme, UriMissingHost, + ClientCollected, + RequestCollected, } | https://datatracker.ietf.org/doc/html/rfc2616 @@ -174,6 +175,10 @@ export object Client { } fun start(Request request) > Request !> HttpError { + if (this.collected) { + throw HttpError.ClientCollected; + } + var requestPtr = HttpClientSend( client: this.client, method: request.method, @@ -188,6 +193,8 @@ export object Client { fun collect() > void { if (!this.collected) { + this.collected = true; + HttpClientDeinit(this.client); } } @@ -203,6 +210,10 @@ export object Request { bool collected = false, fun wait() > Response !> HttpError, errors.InvalidArgumentError, HttpParseError { + if (this.collected) { + return error.RequestCollected; + } + if (this.response != null) { throw errors.InvalidArgumentError{}; } @@ -210,7 +221,11 @@ export object Request { if (this.request -> request) { HttpRequestWait(request); - return HttpRequestRead(request); + const response = HttpRequestRead(request); + + this.response = response; + + return response; } throw errors.InvalidArgumentError{}; @@ -269,4 +284,4 @@ export object Response { return "HTTP/1.1 500 Internal Server Error"; } -} \ No newline at end of file +} diff --git a/src/memory.zig b/src/memory.zig index 479a4e72..ecf5d75e 100644 --- a/src/memory.zig +++ b/src/memory.zig @@ -708,8 +708,8 @@ pub const GarbageCollector = struct { free(self, ObjMap, obj_map); }, .Enum => { - var obj_enum = ObjEnum.cast(obj).?; - obj_enum.deinit(); + const obj_enum = ObjEnum.cast(obj).?; + self.allocator.free(obj_enum.cases); free(self, ObjEnum, obj_enum); }, diff --git a/src/obj.zig b/src/obj.zig index edbd55f4..431601e1 100644 --- a/src/obj.zig +++ b/src/obj.zig @@ -3358,11 +3358,9 @@ pub const ObjEnum = struct { name: *ObjString, cases: []Value, - allocator: Allocator, - pub fn init(allocator: Allocator, def: *ObjTypeDef) Self { + pub fn init(def: *ObjTypeDef) Self { return Self{ - .allocator = allocator, .type_def = def, .name = def.resolved_type.?.Enum.name, .cases = undefined, @@ -3397,10 +3395,6 @@ pub const ObjEnum = struct { } } - pub fn deinit(self: *Self) void { - self.allocator.free(self.cases); - } - pub inline fn toObj(self: *Self) *Obj { return &self.obj; } diff --git a/src/value.zig b/src/value.zig index 44fe4b73..f6a509f0 100644 --- a/src/value.zig +++ b/src/value.zig @@ -34,6 +34,7 @@ pub const Value = packed struct { pub const TrueBitMask: u64 = 1; pub const TrueMask: u64 = BooleanMask | TrueBitMask; + // FIXME: Their's room to have a bigger integer. How would MIR handle it? pub const IntegerMask: u64 = TaggedValueMask | (@as(u64, TagInteger) << 32); pub const NullMask: u64 = TaggedValueMask | (@as(u64, TagNull) << 32); pub const VoidMask: u64 = TaggedValueMask | (@as(u64, TagVoid) << 32); diff --git a/tests/manual/006-http-client.buzz b/tests/manual/006-http-client.buzz index df092f30..b0663cb4 100644 --- a/tests/manual/006-http-client.buzz +++ b/tests/manual/006-http-client.buzz @@ -1,4 +1,3 @@ -import "std"; import "http"; import "debug"; import "errors";