Skip to content

Instantly share code, notes, and snippets.

@andrewrk
Last active June 19, 2024 19:44
Show Gist options
  • Save andrewrk/d8014959638ff67ff87a183b639304e2 to your computer and use it in GitHub Desktop.
Save andrewrk/d8014959638ff67ff87a183b639304e2 to your computer and use it in GitHub Desktop.
determining if a client can block on non-accepted connections to a server
$ ./client
info: connecting first
info: poll first
info: connecting second
info: poll second
info: connecting third (note: returns immediately)
info: poll third (note: returns immediately)
info: sleep 5 seconds
info: exit
$ ./server
info: listening
info: accepting first
info: accepting second
info: blocking for 999 seconds
write(2, "info: connecting first\n", 23info: connecting first
) = 23
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3
connect(3, {sa_family=AF_UNIX, sun_path="unix_socket"}, 110) = 0
write(2, "info: poll first\n", 17info: poll first
) = 17
poll([{fd=3, events=POLLOUT}], 1, -1) = 1 ([{fd=3, revents=POLLOUT}])
write(2, "info: connecting second\n", 24info: connecting second
) = 24
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 4
connect(4, {sa_family=AF_UNIX, sun_path="unix_socket"}, 110) = 0
write(2, "info: poll second\n", 18info: poll second
) = 18
poll([{fd=4, events=POLLOUT}], 1, -1) = 1 ([{fd=4, revents=POLLOUT}])
write(2, "info: connecting third\n", 23info: connecting third
) = 23
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 5
connect(5, {sa_family=AF_UNIX, sun_path="unix_socket"}, 110) = 0
write(2, "info: poll third\n", 17info: poll third
) = 17
poll([{fd=5, events=POLLOUT}], 1, -1) = 1 ([{fd=5, revents=POLLOUT}])
write(2, "info: sleep 5 seconds\n", 22info: sleep 5 seconds
) = 22
nanosleep({tv_sec=5, tv_nsec=0}, {tv_sec=1, tv_nsec=59542756}) = ? ERESTART_RESTARTBLOCK (Interrupted by signal)
const std = @import("std");
pub fn main() !void {
std.log.info("connecting first", .{});
const conn1 = try connectUnixSocket("unix_socket");
var pfd1 = [1]std.posix.pollfd{.{
.fd = conn1.handle,
.events = std.posix.POLL.OUT,
.revents = 0,
}};
std.log.info("poll first", .{});
_ = try std.posix.poll(&pfd1, -1);
std.log.info("connecting second", .{});
const conn2 = try connectUnixSocket("unix_socket");
var pfd2 = [1]std.posix.pollfd{.{
.fd = conn2.handle,
.events = std.posix.POLL.OUT,
.revents = 0,
}};
std.log.info("poll second", .{});
_ = try std.posix.poll(&pfd2, -1);
std.log.info("connecting third", .{});
const conn3 = try connectUnixSocket("unix_socket");
var pfd3 = [1]std.posix.pollfd{.{
.fd = conn3.handle,
.events = std.posix.POLL.OUT,
.revents = 0,
}};
std.log.info("poll third", .{});
_ = try std.posix.poll(&pfd3, -1);
std.log.info("sleep 5 seconds", .{});
std.time.sleep(std.time.ns_per_s * 5);
std.log.info("exit", .{});
}
pub fn connectUnixSocket(path: []const u8) !std.net.Stream {
const posix = std.posix;
// I tried this with and without NONBLOCK with the same results.
const sockfd = try posix.socket(
posix.AF.UNIX,
posix.SOCK.STREAM | posix.SOCK.CLOEXEC | posix.SOCK.NONBLOCK,
0,
);
errdefer std.net.Stream.close(.{ .handle = sockfd });
var addr = try std.net.Address.initUnix(path);
try posix.connect(sockfd, &addr.any, addr.getOsSockLen());
return .{ .handle = sockfd };
}
const std = @import("std");
pub fn main() !void {
const addr = try std.net.Address.initUnix("unix_socket");
std.log.info("listening", .{});
var server = try addr.listen(.{});
std.log.info("accepting first", .{});
const conn1 = try server.accept();
_ = conn1;
std.log.info("accepting second", .{});
const conn2 = try server.accept();
_ = conn2;
std.log.info("blocking for 999 seconds", .{});
std.time.sleep(std.time.ns_per_s * 999);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment