networking · intermediate · ~15 min
The drain loop for edge-triggered I/O.
Implement int drain(int (*read_fn)(char *, int), char *buf, int cap, int *out_total).
read_fn(dst, n) returns:
>0: bytes copied into dst0: EOF — peer closed-1: EAGAIN (no more data right now)-2: real errorCall read_fn repeatedly into buf + offset, advancing offset by the return,
until read_fn returns 0, -1, or -2. Cap the total at cap bytes (refuse to
loop forever filling memory).
Return:
0 on EAGAIN or EOF (success — drained as far as possible).-1 on real error.Set *out_total to the total bytes read in either case.
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.
Stub read function + buffer + cap.
0 / -1, plus *out_total.
Cap the total bytes; never overrun buf.
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.