epoll

package
v1.5.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Overview

Package epoll implements the epoll-based I/O engine for Linux.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine implements the epoll-based I/O engine.

func New

func New(cfg resource.Config, handler stream.Handler) (*Engine, error)

New creates a new epoll engine.

func (*Engine) Addr

func (e *Engine) Addr() net.Addr

Addr returns the bound listener address.

func (*Engine) AdoptConn added in v1.5.6

func (e *Engine) AdoptConn(fd int, carry engine.Carryover) error

AdoptConn implements engine.TransplantTarget for the epoll engine (#383 reverse direction). The source engine (io_uring) has ALREADY detached fd from its own rings (cancelled the recv, released its connState) before calling this, handing epoll a real, connected, non-blocking socket at an HTTP/1 request boundary. AdoptConn routes it to one loop (round-robin) and schedules the attach on that loop's own thread via the eventfd wakeup, where epoll_ctl + connState setup are safe. Safe to call from any goroutine; on a returned error the caller still owns fd.

func (*Engine) Listen

func (e *Engine) Listen(ctx context.Context) error

Listen starts the epoll engine and blocks until context is canceled.

func (*Engine) Metrics

func (e *Engine) Metrics() engine.EngineMetrics

Metrics returns a snapshot of engine metrics.

func (*Engine) NumWorkers added in v1.4.0

func (e *Engine) NumWorkers() int

NumWorkers returns the number of worker event loops. Required by engine.EventLoopProvider.

func (*Engine) PauseAccept added in v0.3.0

func (e *Engine) PauseAccept() error

PauseAccept stops accepting new connections. Synchronous — blocks until every loop has closed its listen FD (and drained pending accepts in the kernel queue with FIN, not RST). The adaptive engine relies on this: until the standby's listen sockets are gone from the SO_REUSEPORT routing pool, fresh dials may land on the about-to-pause engine and get RST'd when its FD closes. Synchronous Pause means callers can expose Addr() knowing only the active engine listens.

func (*Engine) ResumeAccept added in v0.3.0

func (e *Engine) ResumeAccept() error

ResumeAccept starts accepting new connections again. Wakes any suspended loops so they re-create listen sockets.

func (*Engine) Sendfile added in v1.5.0

func (e *Engine) Sendfile(fdOut int, file *os.File, offset, length int64, headers []byte) (int64, error)

Sendfile implements engine.SendfileCapable using sendfile(2) (celeris#317). Writes `headers` via write(2) then transfers the file body to the socket via the kernel's zero-copy path. Returns the number of body bytes sent.

The connection FD must be non-blocking (the epoll engine sets SOCK_NONBLOCK on accept). EAGAIN is surfaced to the caller, which defers the rest of the response to the next epoll_wait iteration. The source file is owned by the caller; the engine does not close it.

func (*Engine) Shutdown

func (e *Engine) Shutdown(_ context.Context) error

Shutdown is a no-op for the epoll engine — graceful shutdown is driven by context cancellation on Listen's parent context. The Server calls Listen with its managed context and cancels it during Server.Shutdown; the Listen goroutine returns after running Loop.shutdown (which closes connections and joins async dispatch goroutines via asyncWG).

The context parameter is accepted for interface parity with engines that do run async drain operations on Shutdown (e.g. std's http.Server.Shutdown), and for future use if epoll Shutdown gains explicit drain semantics.

func (*Engine) StartTransplant added in v1.5.6

func (e *Engine) StartTransplant(target engine.TransplantTarget)

StartTransplant begins draining this engine's established HTTP/1 keep-alive connections to target (an io_uring engine) as each reaches a clean request boundary (#383). Idempotent and safe to call from any goroutine. The adaptive engine calls this after promoting epoll→io_uring so the pinned keep-alives migrate onto io_uring instead of being stranded on the now-standby epoll — the hollow-promotion forfeit documented in #396.

func (*Engine) StopTransplant added in v1.5.6

func (e *Engine) StopTransplant()

StopTransplant halts any in-progress drain (#383). Called when the adaptive engine reverts to epoll, so freshly-accepted conns are not migrated away.

func (*Engine) Type

func (e *Engine) Type() engine.EngineType

Type returns the engine type.

func (*Engine) WorkerLoop added in v1.4.0

func (e *Engine) WorkerLoop(n int) engine.WorkerLoop

WorkerLoop returns the worker loop at index n. Out-of-range n is reduced modulo NumWorkers so callers can hash a connection / FD across the available pool without first reading NumWorkers. Negative n is mirrored to the positive side. Panics only when the engine has no loops (i.e. Listen has not yet started).

type Loop

type Loop struct {
	// contains filtered or unexported fields
}

Loop is an epoll-based event loop worker.

func (*Loop) CPUID added in v1.4.0

func (l *Loop) CPUID() int

CPUID returns the CPU the worker is pinned to, or -1 if the worker was not successfully pinned (platform.PinToCPU best-effort).

func (*Loop) RegisterConn added in v1.4.0

func (l *Loop) RegisterConn(fd int, onRecv func([]byte), onClose func(error)) error

RegisterConn adds fd to this worker's epoll interest set and installs the data and close callbacks. fd must already be in non-blocking mode; the caller retains ownership of the fd (UnregisterConn does not close it).

Returns an error if fd is already registered as an HTTP conn on this worker or already registered as a driver conn.

func (*Loop) UnregisterConn added in v1.4.0

func (l *Loop) UnregisterConn(fd int) error

UnregisterConn removes fd from this worker's interest set and schedules the onClose callback (with a nil error) to fire on the next worker iteration. The fd itself is NOT closed — the driver owns its lifetime.

func (*Loop) Write added in v1.4.0

func (l *Loop) Write(fd int, data []byte) error

Write enqueues data for transmission on fd. Returns engine.ErrUnknownFD if fd is not registered on this worker, or engine.ErrQueueFull if the pending backlog would exceed driverWriteCap.

The call is non-blocking: it performs at most one write(2) inline when the socket is idle and otherwise arms EPOLLOUT so the worker flushes the remainder on the next iteration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL