Skip to content

Commit 0ea2979

Browse files
committed
santisation
1 parent ea51d67 commit 0ea2979

40 files changed

Lines changed: 1386 additions & 106 deletions

src/zingcore/2.5/MIGRATION.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,11 @@ int got = read_frame_wait(loop, aio, watch_id, ack, sizeof(ack));
184184
uint8_t done[65536];
185185
got = read_frame_wait(loop, aio, watch_id, done, sizeof(done));
186186
187-
// See abi/FILE_AIO_PROTOCOL.md for normative framing and parsing recipes.
187+
// Backpressure note:
188+
// - file/aio has a bounded submission queue.
189+
// - If you receive an immediate ERROR with msg "queue full", stop submitting new jobs,
190+
// drain completions/events, and retry after observing progress.
191+
// See abi/FILE_AIO_PROTOCOL.md for normative framing, parsing recipes, and the backpressure contract.
188192
```
189193

190194
Sandboxing is still via env vars (`ZI_FS_ROOT`, `ZI_NET_ALLOW`), but the path is in params.

src/zingcore/2.5/Makefile

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ CFLAGS ?= -std=c11 -O2 -Wall -Wextra -Wpedantic
33
AR ?= ar
44
ARFLAGS ?= rcs
55

6+
# Auto header dependencies (prevents stale objects when headers change).
7+
DEPFLAGS ?= -MMD -MP
8+
69
BUILD ?= build
710
DIST ?= dist
811
DIST_DEBUG ?= $(DIST)/debug
@@ -69,6 +72,8 @@ OBJ := \
6972
$(BUILD)/zi_hopabi25.o \
7073
$(BUILD)/zi_telemetry.o
7174

75+
TESTOBJ = $(addprefix $(BUILD)/,$(addsuffix .o,$(TESTS)))
76+
7277
TESTS := test_caps test_async_registry test_zingcore25_api test_problem test_telemetry_jsonl test_sysabi25_min_core test_sysabi25_ctl_caps_list test_sysabi25_file_aio_cap test_sysabi25_tcp_cap test_sysabi25_tcp_loop_connect_cap test_sysabi25_http_cap test_sysabi25_http_loop_cap test_sysabi25_argv_cap test_sysabi25_env_cap test_sysabi25_hopper_cap test_sysabi25_event_bus_cap test_sysabi25_sys_info_cap test_sysabi25_sys_loop_cap test_bus_rpc_v1 test_hopabi25_basic
7378

7479
EXAMPLES := stdio_caps_demo all_caps_demo hopabi_guest_demo
@@ -87,23 +92,25 @@ dist-dirs:
8792

8893
$(BUILD)/%.o: $(SRCDIR)/%.c | dirs
8994
mkdir -p $(dir $@)
90-
$(CC) $(CFLAGS) -I$(INCDIR) -c $< -o $@
95+
$(CC) $(CFLAGS) $(DEPFLAGS) -I$(INCDIR) -MF $(@:.o=.d) -MT $@ -c $< -o $@
9196

9297
$(BUILD)/test_%.o: $(TESTDIR)/test_%.c | dirs
9398
mkdir -p $(dir $@)
94-
$(CC) $(CFLAGS) -I$(INCDIR) -c $< -o $@
99+
$(CC) $(CFLAGS) $(DEPFLAGS) -I$(INCDIR) -MF $(@:.o=.d) -MT $@ -c $< -o $@
95100

96101
$(LIB): $(OBJ)
97102
$(AR) $(ARFLAGS) $@ $^
98103

99-
test: $(LIB) $(addprefix $(BUILD)/,$(addsuffix .o,$(TESTS)))
104+
test: $(LIB) $(TESTOBJ)
100105
@set -e; \
101106
for t in $(TESTS); do \
102107
bin="$(BUILD)/$$t"; \
103108
$(CC) $(CFLAGS) "$(BUILD)/$$t.o" $(LIB) -o "$$bin"; \
104109
"$$bin"; \
105110
done
106111

112+
-include $(OBJ:.o=.d) $(TESTOBJ:.o=.d)
113+
107114
examples: $(LIB)
108115
@set -e; \
109116
for e in $(EXAMPLES); do \

src/zingcore/2.5/abi/FILE_AIO_PROTOCOL.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,74 @@ OK payload:
250250
- Submission errors (bad payload, out-of-bounds pointers, queue full) are returned as an immediate ERROR response.
251251
- Execution errors (open/read/write failures, unknown `file_id`, sandbox denial) are returned as an `EV_DONE` ERROR frame.
252252

253+
## Backpressure (guest-level contract)
254+
255+
`file/aio` has a bounded internal submission queue. When the queue is full, the host MUST reject additional job submissions.
256+
257+
### What the guest observes
258+
259+
- The job submission itself is still a normal ZCL1 request written to the `file/aio` handle.
260+
- If the queue is full, the host MUST return an **immediate** ZCL1 ERROR response for that `(op, rid)`.
261+
262+
In the zingcore 2.5 reference implementation, this error uses:
263+
264+
- `trace_len/trace` = `"file.aio"`
265+
- `msg_len/msg` = `"queue full"`
266+
267+
These strings are not a general ZCL1 standard, but they are the stable shape used by zingcore 2.5 today.
268+
Guests SHOULD treat this condition as a retryable backpressure signal.
269+
270+
### How to wait (no “queue has space” readiness)
271+
272+
The intended guest strategy is:
273+
274+
- Guests SHOULD keep a bounded number of in-flight jobs.
275+
- On a `queue full` submission error, guests SHOULD stop submitting new jobs for that queue.
276+
- Guests SHOULD drain completions/events from the same `file/aio` handle.
277+
- Guests SHOULD use `sys/loop` to block until the queue becomes **readable** (meaning: there are frames to read), then read and process them.
278+
- After observing progress (typically one or more `EV_DONE` frames), guests SHOULD retry the submission.
279+
280+
This avoids busy-looping while still fitting the single-wait model.
281+
282+
### Submission writable readiness (queue has space)
283+
284+
Guests MAY also watch the `file/aio` handle for `writable` readiness to wait for submission space.
285+
286+
Contract:
287+
288+
- When the submission queue is full, the host SHOULD report the handle as not-writable.
289+
- When the queue transitions from full to having at least one free slot, the host SHOULD report the handle as writable.
290+
291+
This is a readiness hint and is still subject to races:
292+
293+
- A guest might observe `writable` and still lose a race and get `queue full`.
294+
- Guests MUST handle `queue full` as the authoritative signal.
295+
296+
Intended guest pattern:
297+
298+
- On `queue full`, WATCH `writable` and `POLL`.
299+
- Retry submission on READY(writable).
300+
301+
Pseudocode sketch:
302+
303+
```c
304+
for (;;) {
305+
submit_job(aio, rid, ...);
306+
frame ack = read_frame_wait(loop, aio, watch_id);
307+
308+
if (ack.status == ERROR && ack.trace == "file.aio" && ack.msg == "queue full") {
309+
// Backpressure: wait for progress (completions) before retrying.
310+
do {
311+
frame f = read_frame_wait(loop, aio, watch_id);
312+
// process f (ACK/EV_DONE/ERROR)
313+
} while (!saw_ev_done_for_any_job());
314+
continue; // retry submit
315+
}
316+
317+
break;
318+
}
319+
```
320+
253321
## Notes
254322

255323
- This version returns READ data inline in completion frames. Large reads may be truncated by the runtime.

src/zingcore/2.5/abi/HTTP_PROTOCOL.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,15 @@ If an environment variable is unset or invalid, implementations SHOULD fall back
108108
### Default transfer semantics (v1)
109109

110110
Implementations SHOULD default to conservative semantics:
111-
- Reject `Transfer-Encoding: chunked` requests (treat as `ZI_E_INVALID`) unless explicitly supported.
111+
- If `Transfer-Encoding: chunked` is not supported, reject such requests (treat as `ZI_E_INVALID`).
112+
- If `Transfer-Encoding: chunked` is supported, the runtime MUST decode the chunked framing and expose the decoded bytes as a request body `STREAM` (i.e., `body_kind=2`).
112113
- Close the connection after completing a response, unless keep-alive is explicitly supported.
113114

115+
Notes (reference runtime behavior):
116+
- Server-side incoming requests with `Transfer-Encoding: chunked` are supported and are exposed as `body_kind=STREAM`.
117+
- Multipart (Option A) advertisement is conservative; runtimes MAY choose not to advertise `MULTIPART` for chunked bodies.
118+
- Client-side `FETCH` supports `Transfer-Encoding: chunked` responses by decoding and exposing the decoded bytes as `body_kind=STREAM`.
119+
114120
## ZCL1 Operations
115121

116122
All frames use ZCL1 v1 (see `ZCL1_PROTOCOL.md`).
2.02 MB
Binary file not shown.
849 KB
Binary file not shown.
62.6 KB
Binary file not shown.
108 KB
Binary file not shown.
42.2 KB
Binary file not shown.
27.9 KB
Binary file not shown.

0 commit comments

Comments
 (0)