networking · intermediate · ~15 min
The drain loop for edge-triggered I/O.
Write the read-until-EAGAIN loop that edge-triggered epoll requires. Get it wrong and connections silently stall.
Implement int drain(int (*read_fn)(char *, int), char *buf, int cap, int *out_total).
read_fn(dst, n) is a stub that mimics a non-blocking read into dst (up to n bytes) and returns:
>0: number of bytes copied into dst0: EOF — the peer closed-1: EAGAIN — no more data available right now-2: a real errorCall read_fn repeatedly into buf + offset, advancing offset by each positive return, until it returns 0, -1, or -2, or until you have filled cap bytes (so you never loop forever or overrun buf).
read_fn: the stub read function.buf, cap: destination buffer and its capacity.out_total: receives the total bytes read.Return 0 on EAGAIN or EOF (drained as far as possible — success). Return -1 on a real error (-2 from read_fn). In both cases set *out_total to the total bytes read so far.
reads 2 bytes, then 1 byte, then EAGAIN -> returns 0, *out_total = 3, buf = "abc"
EOF on the first call -> returns 0, *out_total = 0
EAGAIN on the first call -> returns 0, *out_total = 0
error (-2) from read_fn -> returns -1, *out_total = bytes read so far
offset reaches cap, even if more data may be available.-1) is NOT an error — it means "done for now". Only -2 returns -1.Edge-triggered epoll requires this loop. Get the loop wrong and connections silently stall — a notorious cause of 'works in dev, fails in prod' bugs.
read_fn, a non-blocking read stub; buf/cap, the destination buffer and its size; out_total for the byte count.
0 on EAGAIN or EOF, -1 on a real error (-2); *out_total set to total bytes read in both cases.
Loop until EOF/EAGAIN/error or cap is reached; never overrun buf; treat EAGAIN as success, not failure.
int drain(int (*read_fn)(char *, int), char *buf, int cap, int *out_total) { /* TODO */ return 0; }
Returning -1 on EAGAIN; treating EAGAIN as fatal.
Immediate EAGAIN (0 bytes read). Cap reached mid-drain.
O(total bytes).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.