linux-sysprog · intermediate · ~10 min
Use alarm() + SIGALRM to bound a read.
Put a time budget on a blocking read using alarm(): if no data arrives within the deadline, the read is interrupted and reported as a timeout.
Implement int read_with_timeout(int fd, char *buf, int cap, int seconds) that reads from fd but gives up after seconds.
fd: the file descriptor to read from.buf, cap: destination buffer and its capacity.seconds: the timeout in seconds.Installs a SIGALRM handler (so the alarm doesn't terminate the process), arms alarm(seconds), performs one read(fd, buf, cap), then cancels the alarm with alarm(0). Returns the number of bytes read on success, or -1 if the read was interrupted by the alarm (i.e. errno == EINTR).
read_with_timeout(pipe_with_data, buf, 16, 3) -> 2 (data was ready, e.g. "hi")
read_with_timeout(empty_pipe, buf, 16, 1) -> -1 (timed out after ~1s)
-1 once the alarm interrupts the read.SA_RESTART — you want the read to return EINTR.alarm(0) after the read.alarm() + a no-op handler is the simplest way to put a time budget on a blocking syscall.
A file descriptor fd, a buffer buf of capacity cap, and a timeout in seconds.
The number of bytes read on success, or -1 if the read was interrupted by the alarm (errno == EINTR).
Install a SIGALRM handler without SA_RESTART, arm alarm(seconds), read once, then alarm(0).
#include <signal.h>
#include <unistd.h>
#include <errno.h>
int read_with_timeout(int fd, char *buf, int cap, int seconds) {
/* TODO */
return -1;
}
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.