libxev
libxev copied to clipboard
Different behavior on mac kqueue and linux
In this PR https://github.com/zen-eth/zig-libp2p/pull/8/files#diff-4b7042b2889c4dd7daa2ceb2cb50d1fd2f25cbff0f4d763646e9bc7f0d59ab3dR579 libxev.zig.
The loop is a threadlocal variable, it should be different eventloop in different thread. The test tested in different thread to dial unavailable address, it works fine on my Mac. But on linux io_uring the test blocking, if switch to epoll, the error below
error: 'transport.tcp.libxev.test.dial in separate thread with error' failed: Error connecting: error.ConnectionRefused
Error connecting: error.ConnectionRefused
expected error.ConnectionRefused, found error.FileDescriptorAlreadyPresentInSet
/home/grapepapa/.zvm/0.13.0/lib/std/posix.zig:3978:19: 0x105a687 in epoll_ctl (test)
.EXIST => return error.FileDescriptorAlreadyPresentInSet,
^
/home/grapepapa/.cache/zig/p/1220d220fe297775b574b0312faaf5afcc0044cbda650d0558ec2dda8fb1a6dc1228/src/backend/epoll.zig:306:17: 0x10595af in tick (test)
return err;
^
/home/grapepapa/.cache/zig/p/1220d220fe297775b574b0312faaf5afcc0044cbda650d0558ec2dda8fb1a6dc1228/src/backend/epoll.zig:96:49: 0x105e2f1 in run (test)
.until_done => while (!self.done()) try self.tick(1),
^
/home/grapepapa/.cache/zig/p/1220d220fe297775b574b0312faaf5afcc0044cbda650d0558ec2dda8fb1a6dc1228/src/dynamic.zig:169:42: 0x105e487 in run (test)
inline else => |tag| try @field(
^
/home/grapepapa/zig-projects/zig-libp2p/src/transport/tcp/libxev.zig:360:9: 0x105e7a5 in dial (test)
try l.run(.until_done);
^
/home/grapepapa/.zvm/0.13.0/lib/std/testing.zig:47:13: 0x105ed59 in expectError__anon_5242 (test)
return error.TestExpectedError;
^
/home/grapepapa/zig-projects/zig-libp2p/src/transport/tcp/libxev.zig:604:5: 0x105f414 in test.dial in separate thread with error (test)
try std.testing.expectError(error.ConnectionRefused, transport.dial(addr1, &channel1));
pub fn dial(self: *XevTransport, addr: std.net.Address, channel: *SocketChannel) !void {
var socket = TCP.init(addr) catch unreachable;
var err: ?anyerror = null;
var connect_cb_data = OpenChannelCallbackData{
.transport = self,
.channel = channel,
.err = &err,
};
var c: xev.Completion = undefined;
var l = getLoop();
socket.connect(&l, &c, addr, OpenChannelCallbackData, &connect_cb_data, connectCallback);
try l.run(.until_done);
if (err) |e| {
return e;
}
}
test "dial in separate thread with error" {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const opts = Options{ .backlog = 128 };
var transport = try XevTransport.init(allocator, opts);
defer transport.deinit();
const addr = try std.net.Address.parseIp("127.0.0.1", 1);
var channel: SocketChannel = undefined;
var result: ?anyerror = null;
const thread = try std.Thread.spawn(.{}, struct {
fn run(t: *XevTransport, a: std.net.Address, c: *SocketChannel, err: *?anyerror) void {
t.dial(a, c) catch |e| {
err.* = e;
};
}
}.run, .{ &transport, addr, &channel, &result });
// Add delay to ensure thread starts
std.time.sleep(10 * std.time.ns_per_ms);
var channel1: SocketChannel = undefined;
const addr1 = try std.net.Address.parseIp("0.0.0.0", 8081);
try std.testing.expectError(error.ConnectionRefused, transport.dial(addr1, &channel1));
thread.join();
try std.testing.expectEqual(result.?, error.ConnectionRefused);
}