@@ -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
3940fn 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
55152const log = std .log .scoped (.zigmirror );
0 commit comments