feat: std.socket nonblocking surface — fcntl, errno, typed _nb wrappers (PLAN-HTTPZ S2)

set_nonblocking (C-variadic fcntl), errno via __error (darwin; C3
selects per-OS), and accept_nb/read_nb/write_nb returning a typed
SockErr — WouldBlock / Closed / Fault — so readiness-loop callers never
parse -1/errno pairs. EINTR retries internally; accept_nb skips
ECONNABORTED. Adds connect, shutdown, socketpair, AF_UNIX, SHUT_*.
examples/1630 pins the result algebra on a socketpair and a nonblocking
TCP listener (WouldBlock on empty backlog, accept after loopback
connect); verified under sx run AND sx build. The .ir snapshot regen is
mechanical: new std decls shift @str/@tag.str numbering and grow the
type table (179 -> 185).
This commit is contained in:
agra
2026-06-12 20:53:35 +03:00
parent da2f76b383
commit 659c43c8d6
78 changed files with 52988 additions and 47974 deletions

View File

@@ -0,0 +1,94 @@
// std.socket nonblocking surface (PLAN-HTTPZ S2): set_nonblocking via
// the C-variadic fcntl, and the typed _nb wrappers' full result
// algebra — bytes, WouldBlock, Closed — on a unix socketpair, plus
// accept_nb on a nonblocking TCP listener (WouldBlock with an empty
// backlog, a connection after a loopback connect).
#import "modules/std.sx";
PORT :: 18931;
main :: () -> i32 {
// ── socketpair: read/write algebra ────────────────────────────────
pair : [2]i32 = ---;
if socket.socketpair(socket.AF_UNIX, socket.SOCK_STREAM, 0, @pair[0]) != 0 {
print("socketpair failed\n");
return 1;
}
a := pair[0];
b := pair[1];
if !socket.set_nonblocking(a) or !socket.set_nonblocking(b) {
print("set_nonblocking failed\n");
return 1;
}
buf : [16]u8 = ---;
n, e := socket.read_nb(a, @buf[0], 16);
if e != error.WouldBlock {
print("empty pair read: expected WouldBlock\n");
return 1;
}
print("empty read: WouldBlock\n");
msg := "ping";
wn, we := socket.write_nb(b, msg.ptr, 4);
if we { print("write_nb failed\n"); return 1; }
if wn != 4 { print("short write: {}\n", wn); return 1; }
rn, re := socket.read_nb(a, @buf[0], 16);
if re { print("read_nb after write failed\n"); return 1; }
if rn != 4 { print("short read: {}\n", rn); return 1; }
print("pair round trip: {} bytes\n", rn);
socket.close(b);
cn, ce := socket.read_nb(a, @buf[0], 16);
if ce != error.Closed {
print("read after peer close: expected Closed\n");
return 1;
}
print("peer close: Closed\n");
socket.close(a);
// ── nonblocking listener: accept_nb ───────────────────────────────
lfd := socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0);
if lfd < 0 { print("listener socket failed\n"); return 1; }
one : i32 = 1;
socket.setsockopt(lfd, socket.SOL_SOCKET, socket.SO_REUSEADDR, @one, 4);
addr : socket.SockAddr = .{
sin_len = 16, sin_family = xx socket.AF_INET,
sin_port = socket.htons(PORT), sin_addr = 0x0100007F, // 127.0.0.1
};
if socket.bind(lfd, @addr, 16) != 0 { print("bind failed\n"); return 1; }
if socket.listen(lfd, 4) != 0 { print("listen failed\n"); return 1; }
if !socket.set_nonblocking(lfd) { print("listener set_nonblocking failed\n"); return 1; }
afd, ae := socket.accept_nb(lfd);
if ae != error.WouldBlock {
print("empty backlog: expected WouldBlock\n");
return 1;
}
print("empty backlog: WouldBlock\n");
// A blocking loopback connect completes the handshake against the
// listen queue without an accept having run yet.
cfd := socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0);
if cfd < 0 { print("client socket failed\n"); return 1; }
if socket.connect(cfd, @addr, 16) != 0 {
print("connect failed: errno {}\n", socket.errno());
return 1;
}
got := -1;
tries := 0;
while got < 0 and tries < 1000 {
c2, ae2 := socket.accept_nb(lfd);
if !ae2 { got = xx c2; }
else if ae2 != error.WouldBlock { print("accept_nb fault\n"); return 1; }
tries += 1;
}
if got < 0 { print("accept never produced the connection\n"); return 1; }
print("accept after connect: ok\n");
socket.close(xx got);
socket.close(cfd);
socket.close(lfd);
print("socket nonblocking ok\n");
return 0;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -311,9 +311,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -794,6 +827,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal i64 @accept_c(ptr %0) #0 {
entry:

View File

@@ -803,9 +803,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1286,6 +1319,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
declare void @BuildOptions.add_link_flag.75(i64, ptr) #0

View File

@@ -819,9 +819,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1302,6 +1335,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
declare void @BuildOptions.add_link_flag.75(i64, ptr) #0

File diff suppressed because one or more lines are too long

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
declare void @BuildOptions.add_link_flag.75(i64, ptr) #0

File diff suppressed because one or more lines are too long

View File

@@ -821,9 +821,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1304,6 +1337,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
declare void @BuildOptions.add_link_flag.75(i64, ptr) #0

View File

@@ -797,9 +797,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1280,6 +1313,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal void @unused_jni(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal i32 @read_int(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal i64 @read_long(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal double @read_double(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal i1 @read_bool(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal ptr @get_window(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal i32 @call_static_max(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal void @unused_jni(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -795,9 +795,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -1278,6 +1311,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
define internal void @unused_jni(ptr %0, ptr %1, ptr %2) #0 {
entry:

View File

@@ -318,9 +318,42 @@ declare i32 @listen(i32, i32) #0
; Function Attrs: nounwind
declare i32 @accept(i32, ptr, ptr) #0
; Function Attrs: nounwind
declare i32 @connect(i32, ptr, i32) #0
; Function Attrs: nounwind
declare i32 @shutdown(i32, i32) #0
; Function Attrs: nounwind
declare i32 @socketpair(i32, i32, i32, ptr) #0
; Function Attrs: nounwind
declare i32 @fcntl(i32, i32, ...) #0
; Function Attrs: nounwind
declare i16 @htons(ptr, i64) #0
; Function Attrs: nounwind
declare ptr @__error() #0
; Function Attrs: nounwind
declare i32 @errno(ptr) #0
; Function Attrs: nounwind
declare i1 @is_wouldblock(ptr, i32) #0
; Function Attrs: nounwind
declare i1 @set_nonblocking(ptr, i32) #0
; Function Attrs: nounwind
declare i64 @accept_nb(ptr, i32) #0
; Function Attrs: nounwind
declare [2 x i64] @read_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare [2 x i64] @write_nb(ptr, i32, ptr, i64) #0
; Function Attrs: nounwind
declare ptr @mem_realloc.3(ptr, ptr, ptr, i64, i64, i64) #0
@@ -801,6 +834,15 @@ declare void @log_emit(ptr, ptr, ptr) #0
; Function Attrs: nounwind
declare void @assert.74(ptr, i1) #0
; Function Attrs: nounwind
declare i32 @clock_gettime(i32, ptr) #0
; Function Attrs: nounwind
declare i64 @now_secs(ptr) #0
; Function Attrs: nounwind
declare i64 @mono_ms(ptr) #0
; Function Attrs: nounwind
declare void @BuildOptions.add_link_flag.75(i64, ptr) #0

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,6 @@
empty read: WouldBlock
pair round trip: 4 bytes
peer close: Closed
empty backlog: WouldBlock
accept after connect: ok
socket nonblocking ok

View File

@@ -1,5 +1,6 @@
// POSIX socket module (macOS only)
// sockaddr_in layout and constants are platform-specific.
// sockaddr_in layout, errno symbol, and constants are platform-specific;
// per-OS selection is PLAN-HTTPZ C3.
libc :: #library "c";
@@ -9,15 +10,23 @@ setsockopt :: (fd: i32, level: i32, optname: i32, optval: *i32, optlen: u32) ->
bind :: (fd: i32, addr: *SockAddr, addrlen: u32) -> i32 #foreign libc;
listen :: (fd: i32, backlog: i32) -> i32 #foreign libc;
accept :: (fd: i32, addr: *SockAddr, addrlen: *u32) -> i32 #foreign libc;
connect :: (fd: i32, addr: *SockAddr, addrlen: u32) -> i32 #foreign libc;
read :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
write :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
close :: (fd: i32) -> i32 #foreign libc;
shutdown :: (fd: i32, how: i32) -> i32 #foreign libc;
socketpair :: (domain: i32, kind: i32, protocol: i32, fds: *i32) -> i32 #foreign libc;
fcntl :: (fd: i32, cmd: i32, ..args: []i32) -> i32 #foreign libc;
// Constants (macOS)
AF_UNIX :i32: 1;
AF_INET :i32: 2;
SOCK_STREAM :i32: 1;
SOL_SOCKET :i32: 0xFFFF;
SO_REUSEADDR :i32: 0x4;
SHUT_RD :i32: 0;
SHUT_WR :i32: 1;
SHUT_RDWR :i32: 2;
// macOS sockaddr_in (16 bytes, has sin_len field)
SockAddr :: struct {
@@ -31,3 +40,98 @@ SockAddr :: struct {
htons :: (port: i64) -> u16 {
cast(u16) (((port & 0xFF) << 8) | ((port >> 8) & 0xFF))
}
// ── nonblocking I/O (PLAN-HTTPZ S2) ──────────────────────────────────
// Typed wrappers over the readiness-loop syscall patterns: callers see
// WouldBlock / Closed / Fault, never a raw -1/errno pair. EINTR is
// retried internally — a readiness loop has nothing useful to do with
// an interrupted syscall except issue it again.
// errno resolves to a real function under the C macro: `__error` on
// darwin, `__errno_location` on linux (C3 selects per-OS).
errno_slot :: () -> *i32 #foreign libc "__error";
// fcntl file-status flags + errno values (macOS).
F_GETFL :i32: 3;
F_SETFL :i32: 4;
O_NONBLOCK :i32: 4;
EINTR :i32: 4;
EPIPE :i32: 32;
EAGAIN :i32: 35; // == EWOULDBLOCK on darwin (and linux's 11 == its EWOULDBLOCK)
EINPROGRESS :i32: 36;
ECONNABORTED :i32: 53;
ECONNRESET :i32: 54;
errno :: () -> i32 {
return errno_slot().*;
}
is_wouldblock :: (e: i32) -> bool {
return e == EAGAIN;
}
// Put `fd` in nonblocking mode (reads/writes/accepts return EAGAIN
// instead of parking the thread). False when fcntl refuses.
set_nonblocking :: (fd: i32) -> bool {
flags := fcntl(fd, F_GETFL);
if flags < 0 { return false; }
return fcntl(fd, F_SETFL, flags | O_NONBLOCK) >= 0;
}
// Failure classes for the _nb wrappers.
// WouldBlock — no data/space/pending connection right now; wait for
// readiness and retry.
// Closed — the peer is gone: EOF on read, EPIPE/ECONNRESET on
// write, ECONNRESET on read.
// Fault — any other errno (caller treats the fd as broken).
SockErr :: error {
WouldBlock,
Closed,
Fault,
}
// Accept one pending connection on a nonblocking listener. A connection
// that died between queueing and accept (ECONNABORTED) is skipped, not
// surfaced — the listener is fine.
accept_nb :: (fd: i32) -> (i32, !SockErr) {
while true {
c := accept(fd, null, null);
if c >= 0 { return c; }
e := errno();
if e == EINTR or e == ECONNABORTED { continue; }
if is_wouldblock(e) { raise error.WouldBlock; }
raise error.Fault;
}
raise error.Fault;
}
// Read up to `cap` bytes. Returns the byte count (> 0); an orderly EOF
// or a peer reset is Closed.
read_nb :: (fd: i32, buf: [*]u8, cap: usize) -> (i64, !SockErr) {
while true {
n := read(fd, buf, cap);
if n > 0 { return xx n; }
if n == 0 { raise error.Closed; }
e := errno();
if e == EINTR { continue; }
if is_wouldblock(e) { raise error.WouldBlock; }
if e == ECONNRESET { raise error.Closed; }
raise error.Fault;
}
raise error.Fault;
}
// Write up to `len` bytes, returning how many the kernel took (possibly
// fewer — the caller continues from there on the next writability).
write_nb :: (fd: i32, buf: [*]u8, len: usize) -> (i64, !SockErr) {
while true {
n := write(fd, buf, len);
if n >= 0 { return xx n; }
e := errno();
if e == EINTR { continue; }
if is_wouldblock(e) { raise error.WouldBlock; }
if e == EPIPE or e == ECONNRESET { raise error.Closed; }
raise error.Fault;
}
raise error.Fault;
}