I am using 0.16.0-dev.1912+0cbaaa5eb, and I have this main loop in my code:
pub fn start(server: *Server, io: Io, gpa: Allocator) !void {
var tcp_server = try IpAddress.listen(try IpAddress.parse(
server.info.host,
server.info.port,
), io, .{});
defer tcp_server.deinit(io);
log.debug("Server headers: {s}", .{if (server.info.headers) "true" else "false"});
log.debug("Server max payload: {d}", .{server.info.max_payload});
log.info("Server ID: {s}", .{server.info.server_id});
log.info("Server name: {s}", .{server.info.server_name});
log.info("Server listening on {s}:{d}", .{ server.info.host, server.info.port });
var client_group: Group = .init;
defer {
log.debug("Canceling client group", .{});
client_group.cancel(io); // the panic seems to happen when I call this.
}
const read_buffer_size, const write_buffer_size = getBufferSizes(io);
log.debug("read buf: {d} write buf: {d}", .{ read_buffer_size, write_buffer_size });
var id: usize = 0;
while (true) : (id +%= 1) {
if (server.clients.contains(id)) continue;
log.debug("Accepting next client", .{});
const stream = tcp_server.accept(io) catch |err| {
log.debug("error: {s}", .{@errorName(err)}); // prints error: Canceled
return err;
};
log.debug("Accepted connection {d}", .{id});
_ = client_group.concurrent(io, handleConnectionInfallible, .{
server,
gpa,
io,
id,
stream,
read_buffer_size,
write_buffer_size,
}) catch |err| {
log.err("Could not start concurrent handler for {d}", .{id});
stream.close(io);
return err;
};
}
}
I’m running into this issue when I connect a client to my server, and then cancel this task while the client is connected:
debug: Server headers: true
debug: Server max payload: 1048576
info: Server ID: server-id-123
info: Server name: Zits Server
info: Server listening on 0.0.0.0:5224
debug: read buf: 212992 write buf: 212992
debug: Accepting next client
debug: Accepted connection 0
debug: Accepting next client
^C
info: Shutting down...
debug: error: Canceled
debug: Canceling client group
debug: Client 0 disconnected
thread 13559 panic: reached unreachable code
robby@lambda ~/src/zits$ /home/robby/downloads/zig-x86_64-linux-0.16.0-dev.1912+0cbaaa5eb/lib/std/debug.zig:419:14: 0x1068389 in assert (std.zig)
if (!ok) unreachable; // assertion failure
^
/home/robby/downloads/zig-x86_64-linux-0.16.0-dev.1912+0cbaaa5eb/lib/std/Io/Threaded.zig:260:23: 0x10ca181 in start (std.zig)
assert(!cancel_acknowledged); // group task acknowledged cancelation but did not return `error.Canceled`
^
/home/robby/downloads/zig-x86_64-linux-0.16.0-dev.1912+0cbaaa5eb/lib/std/Io/Threaded.zig:1317:29: 0x111ac8d in worker (std.zig)
runnable.startFn(runnable, &thread, t);
^
/home/robby/downloads/zig-x86_64-linux-0.16.0-dev.1912+0cbaaa5eb/lib/std/Thread.zig:558:13: 0x10f8a50 in callFn__anon_15769 (std.zig)
@call(.auto, f, args);
^
/home/robby/downloads/zig-x86_64-linux-0.16.0-dev.1912+0cbaaa5eb/lib/std/Thread.zig:1499:30: 0x10c8e50 in entryFn (std.zig)
return callFn(f, self.fn_args);
^
/home/robby/downloads/zig-x86_64-linux-0.16.0-dev.1912+0cbaaa5eb/lib/std/os/linux/x86_64.zig:105:5: 0x10f8b05 in clone (std.zig)
asm volatile (
^
The assertion comment “group task acknowledged cancelation but did not return error.Canceled” makes me feel like this is a bug in the std.Io.Threaded implementation, since I cannot return error.Canceled any more than I already am. But given how new this all is, I’m not confident that I’m using it right. I also tried fiddling with calling std.Io.recancel, but it didn’t seem to resolve the issue. Am I doing things wrong or did I run into a bug?