Skip to content

Commit

Permalink
Don't share or reuse timeout_completion
Browse files Browse the repository at this point in the history
Results in undefined behavior when a client disconnects and another reconnects
while the timeout is being monitored:

#436 (comment)
  • Loading branch information
karlseguin committed Feb 20, 2025
1 parent b12eef2 commit e301ba0
Showing 1 changed file with 11 additions and 5 deletions.
16 changes: 11 additions & 5 deletions src/server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,20 @@ const Server = struct {
// a memory poor for our Clietns
client_pool: std.heap.MemoryPool(Client),

timeout_completion_pool: std.heap.MemoryPool(Completion),

// I/O fields
conn_completion: Completion,
close_completion: Completion,
accept_completion: Completion,
timeout_completion: Completion,

// The response to send on a GET /json/version request
json_version_response: []const u8,

fn deinit(self: *Server) void {
self.send_pool.deinit();
self.client_pool.deinit();
self.timeout_completion_pool.deinit();
self.allocator.free(self.json_version_response);
}

Expand Down Expand Up @@ -121,11 +123,16 @@ const Server = struct {
}

fn queueTimeout(self: *Server) void {
const completion = self.timeout_completion_pool.create() catch |err| {
log.err("failed to create timeout completion: {any}", .{err});
return;
};

self.loop.io.timeout(
*Server,
self,
callbackTimeout,
&self.timeout_completion,
completion,
TimeoutCheck,
);
}
Expand All @@ -135,8 +142,7 @@ const Server = struct {
completion: *Completion,
result: TimeoutError!void,
) void {
std.debug.assert(completion == &self.timeout_completion);

self.timeout_completion_pool.destroy(completion);
const client = self.client orelse return;

if (result) |_| {
Expand Down Expand Up @@ -1008,10 +1014,10 @@ pub fn run(
.conn_completion = undefined,
.close_completion = undefined,
.accept_completion = undefined,
.timeout_completion = undefined,
.json_version_response = json_version_response,
.send_pool = std.heap.MemoryPool(Send).init(allocator),
.client_pool = std.heap.MemoryPool(Client).init(allocator),
.timeout_completion_pool = std.heap.MemoryPool(Completion).init(allocator),
};
defer server.deinit();

Expand Down

0 comments on commit e301ba0

Please sign in to comment.