Skip to content

Commit 92c5b3b

Browse files
committed
systemd NOTIFY_SOCKET requires SOCK_DGRAM
1 parent 063fcc3 commit 92c5b3b

3 files changed

Lines changed: 104 additions & 7 deletions

File tree

build.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn build(b: *std.Build) void {
1616

1717
var service_integration: []const u8 = "dummy";
1818

19-
if (b.systemIntegrationOption("systemd", .{ .default = true })) {
19+
if (b.systemIntegrationOption("systemd", .{ .default = target.result.os.tag == .linux })) {
2020
service_integration = "systemd";
2121
}
2222

build.zig.zon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.{
22
.name = .zigmirror,
33
.fingerprint = 0xe8542ef7ee8a8b70,
4-
.version = "1.2.15",
4+
.version = "1.2.16",
55
.minimum_zig_version = "0.17.0-dev.812+5434f85c4",
66
.paths = .{
77
"src",

src/service_integration/systemd.zig

Lines changed: 102 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub fn init(io: std.Io, env: *const std.process.Environ.Map) void {
2323
log.err("NOTIFY_SOCKET path too long!", .{});
2424
return;
2525
};
26+
log.debug("NOTIFY_SOCKET={f}", .{ std.zig.fmtString(socket_path_final) });
2627
}
2728
}
2829

@@ -37,19 +38,115 @@ pub fn stopping(loop: *http.Loop) void {
3738
}
3839

3940
fn notify(io: std.Io, msg: []const u8) void {
41+
_ = io; // maybe someday std.Io.Threaded will support dgram unix sockets...
42+
4043
if (msg.len == 0) return;
4144
const addr = notify_socket_addr orelse return;
42-
var con = addr.connect(io) catch |err| {
45+
46+
const socket_fd = open_socket() catch |err| {
47+
log.err("Failed to open NOTIFY_SOCKET: {t}", .{ err });
48+
return;
49+
};
50+
defer std.Io.Threaded.closeFd(socket_fd);
51+
52+
var storage: std.posix.sockaddr.un = .{
53+
.family = std.posix.AF.UNIX,
54+
.path = undefined,
55+
};
56+
var path_len = addr.path.len;
57+
@memcpy(storage.path[0..path_len], addr.path[addr.path.len - path_len ..]);
58+
if (storage.path.len - path_len > 0) {
59+
@branchHint(.likely);
60+
storage.path[path_len] = 0;
61+
path_len += 1;
62+
}
63+
64+
const addr_len: std.posix.socklen_t = @intCast(@offsetOf(std.posix.sockaddr.un, "path") + path_len);
65+
66+
connect(socket_fd, @ptrCast(&storage), addr_len) catch |err| {
4367
log.err("Failed to connect to NOTIFY_SOCKET: {t}", .{ err });
4468
return;
4569
};
46-
defer con.close(io);
4770

48-
var writer = con.writer(io, &.{});
49-
writer.interface.writeAll(msg) catch {
50-
log.err("Failed to write to NOTIFY_SOCKET: {t}", .{ writer.err orelse error.WriteFailed });
71+
const bytes_written = write(socket_fd, msg) catch |err| {
72+
log.err("Failed to write to NOTIFY_SOCKET: {t}", .{ err });
5173
return;
5274
};
75+
if (bytes_written != msg.len) {
76+
log.err("Full message could not be written to NOTIFY_SOCKET", .{});
77+
return;
78+
}
79+
}
80+
81+
fn open_socket() !std.posix.socket_t {
82+
while (true) {
83+
const rc = std.posix.system.socket(std.posix.AF.UNIX, std.posix.SOCK.DGRAM | std.posix.SOCK.CLOEXEC, 0);
84+
switch (std.posix.errno(rc)) {
85+
.SUCCESS => return @intCast(rc),
86+
.INTR => continue,
87+
.AFNOSUPPORT => return error.AddressFamilyUnsupported,
88+
.INVAL => return error.ProtocolUnsupportedBySystem,
89+
.MFILE => return error.ProcessFdQuotaExceeded,
90+
.NFILE => return error.SystemFdQuotaExceeded,
91+
.NOBUFS => return error.SystemResources,
92+
.NOMEM => return error.SystemResources,
93+
.PROTONOSUPPORT => return error.AddressFamilyUnsupported,
94+
.PROTOTYPE => return error.SocketModeUnsupported,
95+
else => |err| return std.posix.unexpectedErrno(err),
96+
}
97+
}
98+
}
99+
100+
fn connect(fd: std.posix.socket_t, addr: *const std.posix.sockaddr, addr_len: std.posix.socklen_t) !void {
101+
while (true) {
102+
switch (std.posix.errno(std.posix.system.connect(fd, addr, addr_len))) {
103+
.SUCCESS => return,
104+
.INTR => continue,
105+
else => |e| {
106+
switch (e) {
107+
.AFNOSUPPORT => return error.AddressFamilyUnsupported,
108+
.AGAIN => return error.WouldBlock,
109+
.INPROGRESS => return error.WouldBlock,
110+
.ACCES => return error.AccessDenied,
111+
112+
.LOOP => return error.SymLinkLoop,
113+
.NOENT => return error.FileNotFound,
114+
.NOTDIR => return error.NotDir,
115+
.ROFS => return error.ReadOnlyFileSystem,
116+
.PERM => return error.PermissionDenied,
117+
118+
.BADF => |err| return std.Io.Threaded.errnoBug(err), // File descriptor used after closed.
119+
.CONNABORTED => |err| return std.Io.Threaded.errnoBug(err),
120+
.FAULT => |err| return std.Io.Threaded.errnoBug(err),
121+
.ISCONN => |err| return std.Io.Threaded.errnoBug(err),
122+
.NOTSOCK => |err| return std.Io.Threaded.errnoBug(err),
123+
.PROTOTYPE => |err| return std.Io.Threaded.errnoBug(err),
124+
else => |err| return std.posix.unexpectedErrno(err),
125+
}
126+
},
127+
}
128+
}
129+
}
130+
131+
fn write(fd: std.posix.socket_t, data: []const u8) !usize {
132+
while (true) {
133+
const rc = std.posix.system.write(fd, data.ptr, data.len);
134+
switch (std.posix.errno(rc)) {
135+
.SUCCESS => return @intCast(rc),
136+
.INTR => continue,
137+
.INVAL => |err| return std.Io.Threaded.errnoBug(err),
138+
.FAULT => |err| return std.Io.Threaded.errnoBug(err),
139+
.AGAIN => return error.WouldBlock,
140+
.BADF => |err| return std.Io.Threaded.errnoBug(err),
141+
.DESTADDRREQ => |err| return std.Io.Threaded.errnoBug(err),
142+
.IO => return error.InputOutput,
143+
.PERM => return error.PermissionDenied,
144+
.PIPE => return error.BrokenPipe,
145+
.CONNRESET => |err| return std.Io.Threaded.errnoBug(err),
146+
.BUSY => return error.DeviceBusy,
147+
else => |err| return std.posix.unexpectedErrno(err),
148+
}
149+
}
53150
}
54151

55152
const log = std.log.scoped(.zigmirror);

0 commit comments

Comments
 (0)