Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions plugin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ fn initPlugin(_: *anyopaque) anyerror!void {
const beside = try std.fmt.allocPrint(gpa, "{s}/agent.sock", .{dir});
const socket_path = if (beside.len < 100) beside else blk: {
gpa.free(beside);
// Windows has no `/tmp`, and its process ids are not `pid_t`s.
if (comptime builtin.os.tag == .windows) {
const temp = if (std.c.getenv("TEMP")) |t| std.mem.span(t) else return error.NoTempDir;
break :blk try std.fmt.allocPrint(gpa, "{s}\\fizzy-agent-{d}.sock", .{ temp, std.os.windows.GetCurrentProcessId() });
}
break :blk try std.fmt.allocPrint(gpa, "/tmp/fizzy-agent-{d}.sock", .{std.c.getpid()});
};
server = .{
Expand All @@ -73,11 +78,13 @@ fn initPlugin(_: *anyopaque) anyerror!void {
}

/// `<plugins>/agent/connection.zon`: where the socket is, and the token a client says hello with.
/// Readable by this user only.
/// Readable by this user only: by its mode, or on Windows by the profile directory's own ACL, which a
/// new file inherits.
fn writeConnection(dir: []const u8, socket_path: []const u8, token: []const u8) !void {
const path = try std.fmt.allocPrint(host.allocator, "{s}/connection.zon", .{dir});
defer host.allocator.free(path);
const file = try std.Io.Dir.cwd().createFile(dvui.io, path, .{ .permissions = .fromMode(0o600) });
const permissions: std.Io.File.Permissions = if (comptime builtin.os.tag == .windows) .default_file else .fromMode(0o600);
const file = try std.Io.Dir.cwd().createFile(dvui.io, path, .{ .permissions = permissions });
defer file.close(dvui.io);
var buf: [1024]u8 = undefined;
var w = file.writer(dvui.io, &buf);
Expand Down
15 changes: 9 additions & 6 deletions src/Server.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const std = @import("std");
const builtin = @import("builtin");
const Io = std.Io;

const has_wake_pipe = builtin.os.tag != .windows;

gpa: std.mem.Allocator,
io: Io,
socket_path: []u8,
Expand All @@ -32,8 +34,9 @@ stopping: std.atomic.Value(bool) = .init(false),
/// A pipe `stop` writes to, which wakes the thread waiting to accept (`run`). Waking it by
/// connecting to the socket's path reaches whoever listens there now, which is not always this
/// server: a fizzy taking over from this one (a restart's handover, on the same profile) has made
/// the path its own. Not on Windows, which keeps connecting.
wake_pipe: [2]std.c.fd_t = .{ -1, -1 },
/// the path its own. Not on Windows, whose descriptors are handles, not small integers to poll a
/// pipe beside a socket with: it keeps connecting.
wake_pipe: if (has_wake_pipe) [2]std.c.fd_t else void = if (has_wake_pipe) .{ -1, -1 } else {},
/// The socket file this server made, by inode: `stop` removes the path only while it is still this
/// one, not the socket a fizzy taking over has made there since.
socket_inode: ?std.Io.File.INode = null,
Expand Down Expand Up @@ -123,15 +126,15 @@ pub fn stop(self: *Server) void {
for (self.conns.items) |c| if (!c.done.load(.acquire)) c.stream.shutdown(self.io, .both) catch {};
}
// Wake the thread waiting to accept.
if (self.wake_pipe[1] >= 0) {
if (has_wake_pipe and self.wake_pipe[1] >= 0) {
_ = std.c.write(self.wake_pipe[1], "x", 1);
} else if (Io.net.UnixAddress.init(self.socket_path)) |addr| {
// No pipe: a thread in `accept` wakes when someone connects, so be that someone.
if (addr.connect(self.io)) |s| s.close(self.io) else |_| {}
} else |_| {}
if (self.thread) |t| t.join();
self.thread = null;
for (&self.wake_pipe) |*fd| if (fd.* >= 0) {
if (has_wake_pipe) for (&self.wake_pipe) |*fd| if (fd.* >= 0) {
_ = std.c.close(fd.*);
fd.* = -1;
};
Expand Down Expand Up @@ -160,11 +163,11 @@ fn run(self: *Server) void {
return;
};
if (Io.Dir.cwd().statFile(self.io, self.socket_path, .{})) |st| self.socket_inode = st.inode else |_| {}
if (comptime builtin.os.tag != .windows) {
if (has_wake_pipe) {
if (std.c.pipe(&self.wake_pipe) != 0) self.wake_pipe = .{ -1, -1 };
}
while (!self.stopping.load(.acquire)) {
if (self.wake_pipe[0] >= 0) {
if (has_wake_pipe and self.wake_pipe[0] >= 0) {
// Until someone connects, or `stop` writes to the pipe.
var fds = [_]std.posix.pollfd{
.{ .fd = self.listener.?.socket.handle, .events = std.posix.POLL.IN, .revents = 0 },
Expand Down