Skip to content

Day48 - Epoll + Timerfd + Idle Timeout

Overview

In this lab, we extend the epoll-based TCP server by integrating timerfd to implement idle timeout handling for multiple clients.

The server now supports:

  • Multi-client connection (epoll)
  • Non-blocking sockets
  • TX queue with partial send handling
  • Periodic timer event using timerfd
  • Idle timeout detection and automatic client cleanup

timerfd Basics

Key APIs

  • timerfd_create()
  • timerfd_settime()
  • read()

Important Concept

read(timerfd) does NOT return time.

It returns:

number of expirations since last read

Example

timer interval = 1 sec

If read every second:
    expirations = 1

If read after 5 seconds:
    expirations = 5

Why timerfd with epoll?

Compared to other approaches:

Method Problem
sleep() blocks thread
signal complex, race conditions
thread timer synchronization overhead

timerfd advantages:

  • file descriptor based
  • works naturally with epoll
  • no signal handling
  • no extra thread

Idle Timeout Design

Architecture

timerfd (1 sec tick)
epoll event loop
scan all clients
check idle time
destroy timed-out clients

Key Design Choice

We use:

Single global timerfd
+ per-client timestamp

Instead of:

Per-client timerfd

Trade-offs

Approach Pros Cons
Global timer + scan simple, scalable O(N) scan
Per-client timerfd precise timeout complex, many fd

Client Data Structure

struct client_ctx {
    int fd;
    uint64_t last_active_ms;

    struct tx_queue txq;

    struct client_ctx *next;
};

Server Data Structure

struct server_ctx {
    int listen_fd;
    int epoll_fd;
    int timer_fd;

    uint64_t timer_ms;

    struct client_ctx *client_list;
};

Lifecycle Management

Accept

accept()
    → create client_ctx
    → add epoll
    → set last_active_ms
    → add to client_list

Activity Update

EPOLLIN (recv > 0)
    → update last_active_ms

Timeout Detection

if ((now - client->last_active_ms) >= TIMEOUT_MS)
    client_destroy(...)

Destroy Client

client_destroy():
    → remove from list
    → epoll_ctl(DEL)
    → close(fd)
    → clear TX queue
    → free(client)

epoll vs Client List

Important concept:

epoll = event notification
client_list = state tracking

epoll only tells:

"which fd has event"

It does NOT track all active clients.


Time Source

We use:

clock_gettime(CLOCK_MONOTONIC)

Reasons:

  • not affected by system time changes
  • safe for timeout calculation

Timeout Precision

Timeout is not exact.

Example:

timeout = 10 sec
timer interval = 1 sec

Actual timeout ≈ 10 ~ 11 sec

Summary

This lab introduces:

  • fd-based timer (timerfd)
  • integrating timer into epoll loop
  • scalable idle timeout design
  • clean client lifecycle management

This is a fundamental building block for real-world servers.