Fact-checked by Grok 2 weeks ago

libevent

Libevent is an asynchronous event notification library designed for developing scalable network servers and applications, providing an that executes callback functions in response to events such as activity, timeouts, or signals. Originally developed by Niels Provos starting around 2000 while at the , libevent was created to address the needs of in network servers, with initial copyrights dating to 2000-2007. It is now maintained by Niels Provos, , and Azat Khuzhin under a three-clause BSD license, with ongoing development hosted on . The library has evolved through multiple stable releases, including the latest stable version 2.1.12, released on July 5, 2020, and supports cross-platform builds on , BSD variants, macOS, , and Windows via backends like , , and Windows IOCP. Key features of libevent include support for efficient event multiplexing across operating system-specific mechanisms, such as /dev/poll, select/poll, and event ports, enabling high-performance I/O handling without blocking. It also provides buffered networking capabilities with support for sockets, SSL/TLS integration, , and file transfers, alongside built-in protocols for DNS resolution, HTTP parsing, and a minimal RPC . Multi-threaded applications can utilize isolated event bases or locking for concurrent event processing. Libevent has been widely adopted in high-profile open-source projects, including the Tor anonymity network for its event loop, Memcached for distributed caching, Transmission BitTorrent client, and parts of the Chromium browser engine, underscoring its role in performant, event-driven software.

Introduction and Overview

Purpose and Core Functionality

Libevent is an event notification library designed to execute callback functions in response to specific events, such as changes in file descriptors, timeouts, signals, or regular intervals. It enables developers to build scalable, event-driven applications by providing a unified for handling operations across different operating systems. This approach addresses the need for efficient multiplexing, allowing programs to monitor multiple sources of events without the inefficiencies of traditional blocking calls. At its core, libevent operates through an event base structure (event_base), which serves as the central dispatcher for events in a non-blocking manner. Applications initialize an event base and use functions like event_dispatch() to run the , where registered callbacks are invoked when corresponding events occur. This mechanism supports dynamic addition and removal of events during runtime, facilitating flexible management of resources in high-performance scenarios, such as network servers. By replacing conventional polling techniques—where applications repeatedly check for events—with a reactive , libevent minimizes CPU usage and improves responsiveness. Libevent was initially developed by Niels Provos in 2000 to provide a portable solution for efficient I/O in network programming, tackling challenges like handling thousands of concurrent connections (the ). This foundational work established libevent as a key tool for asynchronous event handling, emphasizing scalability and cross-platform compatibility from its inception.

Licensing and Development

Libevent is released under the three-clause BSD license, which permits broad use, modification, and distribution of the software with minimal restrictions, provided that the , conditions, and are retained in all copies. The library was originally created by Niels Provos, with primary ongoing development and maintenance led by Niels Provos, , and Azat Khuzhin. Notable contributions have also come from individuals such as Mark Ellzey, who has provided patches and enhancements, alongside a wider community of developers. Development occurs through an open-source model hosted on GitHub at the repository libevent/libevent, where users can access the source code, report bugs via issues, and submit pull requests for review. Community discussions and coordination take place on the libevent-users mailing list, archived for public reference, fostering collaborative input on features and fixes. Supporting the developer community, libevent offers comprehensive documentation, including a dedicated programming guide titled "Fast Portable Non-Blocking Network Programming with Libevent," authored by Nick Mathewson, which provides in-depth examples and explanations under a Creative Commons license. Additionally, Doxygen-generated API references are available for various versions, such as 2.1.x and the master branch, enabling detailed exploration of the codebase.

History

Creation and Early Development

Libevent was conceived by Niels Provos in 2000 while he was at the University of Michigan's Center for Information Technology Integration (CITI), with the aim of creating a portable event notification library to simplify operations in network applications. This development addressed the fragmented landscape of event handling mechanisms available at the time, where applications relied on platform-specific implementations that hindered portability and scalability. The library's inception was driven by practical needs in Provos's other projects, including Systrace—a sandboxing tool for policy enforcement—and Honeyd—a daemon for simulating virtual hosts to detect and analyze network attacks—which required an efficient, cross-platform way to manage events and timeouts without custom event loops. These tools highlighted the inefficiencies of ad hoc event processing in early server software, where developers frequently built proprietary solutions to handle concurrent I/O, leading to code duplication and maintenance challenges across systems. The first public release came on April 9, 2002, with version 0.4, marking libevent's availability for broader use and focusing on abstracting low-level APIs such as select() and poll() to enable uniform event notification on diverse operating systems. Initial versions emphasized core portability goals, supporting multiple backends to ensure applications could run seamlessly on various Unix variants without modification, while avoiding dependencies on emerging but non-standard mechanisms like or . This abstraction layer allowed developers to write scalable, non-blocking code once and deploy it widely, reducing the burden of OS-specific adaptations in event-driven architectures.

Major Milestones

Libevent's adoption in prominent open-source projects marked a significant milestone in its evolution, beginning with its integration into the anonymity network around 2005, which enhanced Tor's ability to handle high-volume network I/O efficiently through asynchronous event handling. Similarly, incorporated libevent early in its development to manage scalable operations, enabling the caching system to support tens of thousands of concurrent connections and thereby improving overall throughput in distributed environments. These integrations not only validated libevent's reliability but also spurred performance optimizations in both projects by leveraging its cross-platform event notification capabilities. A pivotal architectural shift occurred with the release of the 2.x series in April 2009, transitioning libevent to a more modular design that separated core event handling from optional protocol support, while introducing native I/O completion ports (IOCP) backend for improved Windows compatibility. This redesign addressed limitations in the 1.x series, enhancing portability and extensibility for diverse operating systems. Documentation efforts advanced notably with the introduction of Doxygen-generated API references in version 1.4, released in November 2007, which provided developers with structured, auto-generated insights into the library's interfaces. Complementing this, the 2.0 era saw the publication of "Developing Applications with libevent" by in 2009, offering comprehensive guidance on patterns and solidifying libevent's accessibility for broader adoption. The library's community expanded in the 2010s through its migration to , which facilitated easier collaboration, issue tracking, and pull requests, leading to a surge in external contributions and ongoing maintenance. This momentum continued into recent years, exemplified by the release of version 2.2.1-alpha in May 2023, introducing features like wepoll backend support and further performance tweaks to prepare for stable deployment.

Technical Features

Event Handling Mechanisms

Libevent supports a variety of types to monitor system conditions without blocking the application. These include read and write events on descriptors, such as sockets, which are triggered when the descriptor becomes ready for input or output operations. Signal events handle signals like SIGINT, allowing applications to respond to interrupts or other system notifications. Timer events can be configured as one-shot or periodic, firing after a specified timeout . exits are managed through signal events, particularly SIGCHLD, enabling detection of process status changes without polling. Events are configured using functions such as event_new() or event_assign(), which associate an event base, a or signal number, event flags (e.g., EV_READ or EV_SIGNAL), a callback , and an optional user argument. When the monitored condition occurs, the callback is invoked asynchronously during the event loop dispatch, passing the event structure, triggered flags, and user data, ensuring the main thread remains non-blocking. This mechanism allows efficient of multiple s, with callbacks executing in the context of the event loop thread. Event persistence is controlled by flags like EV_PERSIST, which keeps an event active after its callback runs, enabling repeated invocations for ongoing conditions such as continuous reads on a ; without this flag, events are one-shot and automatically deactivated post-callback. Notification modes include level-triggered (default), where callbacks fire as long as the condition persists, and edge-triggered (via EV_ET flag, if supported by the backend), which notifies only on state changes to reduce callback frequency in high-volume scenarios. For signal handling, libevent provides a unified through evsignal_new() or similar, abstracting signal delivery into event callbacks that run within the event loop, supporting safe execution of complex logic without direct signal handler constraints. To prevent race conditions in multi-threaded applications, signal events are restricted to a single event base per process (with exceptions for certain backends like ), ensuring consistent handling and avoiding concurrent signal processing issues.

Backend Support

Libevent employs a variety of operating system-specific backends to implement efficient event detection, allowing it to abstract away platform differences while optimizing for performance. The primary backends include on systems, which provides O(1) scalability for monitoring large numbers of file descriptors; on BSD variants and macOS, offering similar high-performance notification for events on files, sockets, and signals; /dev/poll on older systems for efficient polling of multiple descriptors; and event ports (evports) on 10 and later for scalable event delivery. On Windows, libevent supports select() and poll() as standard backends, with integration of I/O Completion Ports (IOCP) for higher scalability in operations, particularly useful in bufferevent contexts. For platforms lacking these advanced mechanisms, libevent falls back to portable but less efficient methods like select() or poll(), ensuring broad compatibility. Backend selection occurs automatically at runtime through the event_base_new() function, which detects and prioritizes the most suitable method based on the operating system and available features. Developers can influence this via the event_config structure, using functions such as event_config_avoid_method() to disable specific backends (e.g., avoiding with "kqueue") or event_config_require_features() to enforce capabilities like edge-triggered notifications (EV_FEATURE_ET). Environment variables, such as EVENT_NOKQUEUE=1, provide an additional way to disable backends without code changes. At , certain backends can be excluded by configuring the build process, for instance, via options in the autotools ./configure script to omit support for or other methods if not needed. These backends enable libevent to scale to thousands of file descriptors efficiently, with modern implementations like and supporting edge-triggered modes to reduce unnecessary wakeups and improve throughput in high-load scenarios. For example, 's ability to handle large numbers of descriptors with minimal overhead makes it ideal for server applications, while 's unified event queue minimizes overhead on BSD systems. However, performance varies by backend; select() is limited to typically around 1,024 descriptors per call due to OS constraints, underscoring the value of automatic fallback only when necessary. Overall, this modular backend design ensures libevent delivers consistent, high-performance event handling across diverse environments.

Utility Components

Libevent includes several higher-level utility components that extend its core event notification capabilities to facilitate common networking and protocol tasks, such as buffered I/O, DNS resolution, HTTP handling, and remote procedure calls. These utilities abstract away low-level details, allowing developers to build efficient, asynchronous applications without directly managing event loops for each operation. The Bufferevent API offers an abstracted interface for input/output operations over transports like sockets or SSL connections, incorporating read and write buffers to handle data streaming efficiently. It supports configurable watermarks—low and high thresholds for read and write buffers—that trigger callbacks when buffer levels are reached, enabling fine-grained control over data flow and preventing buffer overflows or underutilization. Additionally, bufferevents include rate limiting through timeout mechanisms to throttle I/O rates, and options for thread safety and deferred callbacks, making them suitable for concurrent environments. Bufferevents can be created for sockets using functions like bufferevent_socket_new() and extended for SSL via bufferevent_openssl_socket_new(). The evdns library provides asynchronous DNS resolution as a non-blocking alternative to standard resolver functions, integrating seamlessly with libevent's event base for callback-driven hostname lookups. It initializes via evdns_base_new() and parses for configuration, supporting IPv4 and queries through evdns_base_resolve_ipv4() or evdns_getaddrinfo(). Key features include built-in caching of resolved names to reduce redundant queries and automatic nameserver , which tracks server timeouts (defaulting to three attempts) and probes alternatives with starting at 10 seconds. This ensures reliable resolution in dynamic network conditions without blocking the main . Evhttp implements a lightweight HTTP client and framework atop libevent, enabling the creation of servers or clients that handle requests asynchronously. Servers are bound to addresses using evhttp_new() and evhttp_bind_socket(), with for virtual hosts via evhttp_add_virtual_host() to route requests based on host headers. It parses incoming requests, including query arguments, and accommodates for efficient streaming of large responses, while allowing path-specific callbacks through evhttp_set_cb(). This is designed for simplicity, focusing on core HTTP/1.1 compliance without advanced features like (which requires integration with bufferevents). Evrpc offers a straightforward RPC mechanism over HTTP, allowing developers to define and register remote procedures for client-server communication without manual . It relies on an evrpc_base for servers, where commands are declared using macros like EVRPC_HEADER() and registered with EVRPC_REGISTER(), and an evrpc_pool for clients to manage connections and send requests via EVRPC_MAKE_REQUEST(). The protocol handles data marshaling and unmarshaling automatically, often generated by event_rpcgen.py, and supports hooks for custom processing such as or . Timeouts can be set per with evrpc_pool_set_timeout(), ensuring responsive RPC interactions in distributed systems.

Architecture

Event Base and Loop

The event_base structure serves as the core in libevent, encapsulating the backend for event notification (such as , , or select), priority queues to organize pending events, and internal state tracking the loop's operational status. This design allows libevent to efficiently manage event detection and dispatching within a single-threaded loop, while supporting optional locking for safe access from multiple threads. Applications create an event_base using event_base_new() for default configuration or event_base_new_with_config() to specify custom backends or features, enabling tailored performance on different platforms. To support concurrent operations in multi-threaded environments, libevent recommends instantiating multiple event_base instances, one per , as the loop execution remains inherently single-threaded even with locking enabled. Each base maintains its own set of events, preventing cross-thread and ensuring of event processing. The dispatching loop is initiated primarily through event_base_dispatch(), which blocks the calling thread until pending events activate (such as I/O readiness or timeouts) or a manual exit condition is met, then invokes the associated callbacks in priority order. This function returns 0 upon normal termination (no events left), -1 on error, or continues indefinitely until interrupted. For finer control, event_base_loop() offers variants via flags: EVLOOP_NONBLOCK performs a non-blocking check and immediate return if no events are ready, while EVLOOP_ONCE processes active events once without blocking for new ones, facilitating integration with other application logic. Loop termination can be controlled programmatically using event_base_loopexit() to schedule an exit after a specified delay or event_base_loopbreak() for immediate cessation post-callback, both returning 0 on success or -1 on failure. Libevent addresses through configurable multi-level priorities, set via event_base_priority_init() with a maximum of EVENT_MAX_PRIORITIES levels (defaulting to one), allowing events to be added with specific priorities using event_priority_set(). To prevent high-priority events from being unduly delayed by lower-priority callbacks, applications can invoke event_config_set_max_dispatch_interval() during base creation, limiting the dispatch time for lower priorities and periodically re-checking higher ones— for instance, capping intervals at 100 milliseconds with a maximum of 5 callbacks per low-priority batch before yielding to higher priorities.
c
struct event_config *cfg = event_config_new();
event_config_set_max_dispatch_interval(cfg, &msec_100, 5, EVENT_BASE_LOW_PRIORITY);
struct event_base *base = event_base_new_with_config(cfg);
event_config_free(cfg);
This configuration ensures balanced processing, with the base dispatching events from the highest first.

Bufferevents and I/O

Bufferevents in libevent provide a higher-level for managing buffered operations over underlying transports, simplifying by integrating event notifications with handling. A bufferevent combines an underlying transport mechanism, such as a , with input and output s of type struct evbuffer, along with callbacks for reading , writing (including drain events when the write falls below a ), and handling events like errors or connection status changes. This structure allows developers to focus on rather than low-level event polling, with the library automatically invoking read callbacks when arrives and write callbacks as needed to manage outgoing . Creation of bufferevents is tailored to specific transport types; for instance, bufferevent_socket_new() initializes a bufferevent over an existing for sockets, associating it with an event base and optional flags for behavior like locking or deferring callbacks. For secure communications, bufferevent_openssl_socket_new() creates a bufferevent backed by , integrating SSL/TLS directly into the I/O over a socket, which handles handshakes and encrypted data flow transparently. These functions return a struct bufferevent pointer, which can then be enabled for reading, writing, or both using bufferevent_enable(). Buffer management within a bufferevent relies on the evbuffer for efficient data handling. Developers can append data to the output buffer using evbuffer_add() on the bufferevent's output evbuffer (accessed via bufferevent_get_output()), and remove data from the input buffer with evbuffer_remove() from bufferevent_get_input(), enabling seamless reading into application buffers. Evbuffers support chaining multiple buffer segments, which facilitates I/O operations by allowing data to be referenced and passed without unnecessary memcpy calls, optimizing performance in high-throughput scenarios. To mitigate risks like overflows or underflows, libevent employs s for fine-grained control over buffer thresholds. The bufferevent_setwatermark() function sets low and high s for read and write directions; for example, a read low (default 0) triggers the read callback only when sufficient data accumulates, while a read high (default unlimited) pauses reading to prevent excessive growth. Similarly, write watermarks manage output , with the low invoking drain callbacks when the buffer drains below it, and the high signaling when the buffer is full to avoid overflows during error-prone conditions. Error events, such as BEV_EVENT_ERROR for unrecoverable issues or BEV_EVENT_EOF for , are delivered via the event callback, allowing applications to respond appropriately without manual buffer checks.

Usage and API

Basic Event Setup

Libevent's basic event setup begins with the creation of an event base, which serves as the central dispatcher for all events in a program. The function event_base_new() allocates and returns a new event base structure using default settings, automatically selecting the most efficient backend available on the system, such as epoll on Linux or kqueue on BSD derivatives. This function takes no parameters and returns a pointer to the struct event_base on success or NULL on failure, requiring error handling in production code. Once initialized, the event base manages the event loop and associated resources until explicitly freed. To define an individual event, developers use event_new() to allocate and initialize a new structure tied to the event base. This function requires the event base pointer, a (or -1 for non-I/O events like timers), event flags (such as EV_READ for or EV_WRITE for writability), a callback function, and an optional argument passed to the callback. Alternatively, event_assign() can initialize a pre-allocated structure with the same parameters, offering flexibility for memory management in constrained environments. These events remain inactive until added to the event base. Events are activated and scheduled using event_add(), which makes the event pending for processing by the event loop. This function takes the event pointer and an optional timeout specified via a struct timeval, where the structure holds seconds and microseconds (e.g., { .tv_sec = 5, .tv_usec = 0 } for a 5-second delay); passing NULL omits the timeout. Common flags include EV_READ to trigger the callback when data is available for reading on the file descriptor, EV_WRITE for writability, and EV_PERSIST to re-arm the event automatically after firing. The function returns 0 on success or -1 on error, allowing immediate verification. For proper resource management, events must be removed and deallocated when no longer needed. The event_del() function deactivates an event by removing it from the pending queue, returning 0 on success or -1 if the event was not active. Following deactivation, event_free() releases the event's memory, safely handling cases where the event might still be active or pending. Finally, event_base_free() deallocates the event base itself, but only after all associated events have been freed or deleted, as it does not automatically close underlying file descriptors. A simple workflow for basic event setup involves creating an event base, defining a timer event (using -1 as the with EV_TIMEOUT), adding it with a timeout, dispatching the event loop via event_base_dispatch() (which briefly references the event base loop mechanics covered elsewhere), and invoking the callback upon timeout. For instance, the following pseudocode outline demonstrates this flow:
c
#include <event2/event.h>

void timer_callback(evutil_socket_t fd, short events, void *arg) {
    // Handle timer expiration
    struct event_base *base = arg;
    event_base_loopexit(base, NULL);  // Exit loop after callback
}

int main() {
    struct event_base *base = event_base_new();
    if (!base) return 1;

    struct event *timer = event_new(base, -1, EV_TIMEOUT, timer_callback, base);
    struct timeval five_sec = {5, 0};
    event_add(timer, &five_sec);

    event_base_dispatch(base);

    event_free(timer);
    event_base_free(base);
    return 0;
}
This example creates a one-shot timer that exits the loop after 5 seconds, illustrating the core sequence without I/O dependencies.

Advanced Programming Patterns

Libevent supports multi-threaded applications through two primary patterns: isolating event bases per thread or using locking mechanisms for shared access. In the isolated approach, each thread creates and manages its own event_base, ensuring that only a single thread interacts with it, which avoids overhead and simplifies concurrency. This is recommended for , as it allows event loops without contention, with the main thread typically handling listener sockets and dispatching new connections to worker threads' event bases. For shared event bases across threads, Libevent requires initialization of thread support via functions like evthread_use_pthreads() or evthread_use_windows_threads() before creating any event_base, enabling internal locking. After initializing thread support, any event_base created will have internal locking enabled by default, making it safe for multiple s to add or delete events concurrently, though the event loop itself must run in only one thread. To disable locking for a specific base, create an event_config with event_config_new(), set EVENT_BASE_FLAG_NOLOCK using event_config_set_flag(config, EVENT_BASE_FLAG_NOLOCK), and pass it to event_base_new_with_config(config, 0). This approach introduces performance costs from locking and is best for scenarios with infrequent cross-thread modifications. Rate limiting in libevent provides control for bufferevents, particularly useful in applications to prevent overload or enforce quotas per connection or group. The bufferevent_set_rate_limit(bev, cfg) function applies a configuration from an ev_token_bucket_cfg structure, which specifies read/write rates (bytes per tick) and burst sizes, with ticks defaulting to one second for smooth throttling. To create the config, use ev_token_bucket_cfg_new(read_rate, read_burst, write_rate, write_burst, tick_len), where rates limit throughput and bursts allow temporary spikes; setting cfg to NULL disables limiting. For aggregate control, bufferevent_rate_limit_group_new(cfg) creates a shared group, and bufferevent_add_to_rate_limit_group(bev, group) assigns bufferevents to it, with optional minimum shares via bufferevent_rate_limit_group_set_min_share(group, min_share) to ensure fair distribution among members. This mechanism integrates seamlessly with HTTP or servers to cap total , returning 0 on success or -1 on failure. Debugging advanced libevent applications relies on built-in and mode flags to trace processing and diagnose issues like deadlocks or missed callbacks. The event_enable_debug_logging(which) function, introduced in version 2.1.1-alpha, activates verbose debug output, with EVENT_DBG_ALL enabling all categories (e.g., event additions, loop iterations) sent to the default handler or a custom one set via event_set_log_callback(cb); EVENT_DBG_NONE restores defaults. For deeper tracing during development, compile libevent with -DUSE_DEBUG and call event_enable_debug_mode() to log detailed state changes and assertions. These tools help identify threading conflicts or performance bottlenecks without external debuggers, though they incur overhead and should be disabled in production. Performance optimizations in libevent emphasize management and selection to handle high-load scenarios efficiently. To avoid , where low-priority events delay critical ones, assign priorities with event_base_priority_init(base, npriorities) to set up multiple queues (typically 2-3 levels), then event_priority_set(ev, pri) for each event, ensuring higher- callbacks (e.g., urgent reads) execute before lower ones (e.g., ) in the loop; libevent processes all active events at the highest active before descending, preventing . For time-based events, libevent defaults to monotonic s where available via evutil_configure_monotonic_time(, base), using platform-specific clocks like CLOCK_MONOTONIC to ignore adjustments from NTP, thus maintaining accurate timeouts even under —configure explicitly for portability across backends. These patterns, combined with avoiding unnecessary event activations, can sustain thousands of concurrent events with minimal latency.

Platform Support

Operating Systems

Libevent provides full support for various operating systems, leveraging platform-specific event notification mechanisms for optimal performance. On , it utilizes the interface for efficient handling of large numbers of file descriptors. , , , and macOS employ the mechanism, enabling scalable event multiplexing. supports event ports, with fallback to /dev/poll where available. These implementations ensure robust across POSIX-compliant environments. Windows support in libevent is partial, relying on Win32 select and poll for basic event handling, with I/O Completion Ports (IOCP) introduced in version 2.0 for high-performance scenarios on modern Windows systems. However, signal handling is limited due to the absence of native Unix-style signals, requiring workarounds like thread-based polling that may impact efficiency. Libevent also compiles on other platforms, including (using or poll backends), (with caveats such as restricted system calls and sandboxing limitations), and embedded systems like (requiring minor patches for signal restart behavior). For macOS on ARM64 architectures (), support is available starting with version 2.1 and later releases, facilitated by standard compilation tools.

Compilation and Integration

Libevent is primarily built from source using CMake, the recommended build system, or the deprecated Autotools for older compatibility. The latest stable release is version 2.1.12 (July 2020), with an alpha version 2.2.1 available since May 2023. To build with CMake on Unix-like systems, create a build directory, run cmake .. followed by make, and optionally make verify for regression tests before installing with sudo make install. Configuration options include -DEVENT__DISABLE_OPENSSL=ON to exclude OpenSSL support for SSL/TLS, -DEVENT__DISABLE_THREAD_SUPPORT=ON to disable multithreading, and -DEVENT__LIBRARY_TYPE=STATIC to produce only static libraries. For Autotools, first run ./autogen.sh if building from a Git clone, then ./configure with options such as --disable-openssl, --disable-thread-support, or --disable-shared for static builds, followed by make and sudo make install. The library has minimal dependencies, requiring only a standard C library for core functionality. Optional dependencies include or MbedTLS for encryption features and zlib for compression support in certain tests. Build tools like , automake, autoconf, libtool, and are needed depending on the chosen system. Pre-built packages are available through various managers for easier installation. On and systems, the development package libevent-dev provides headers and libraries via sudo apt install libevent-dev. On and RHEL derivatives, use sudo dnf install libevent-devel (or yum on older versions) for the development files. For C++ projects, supports installation with vcpkg install libevent, enabling static or shared linking as needed. Similarly, users can install via conan install libevent, which handles dependencies and supports both static and dynamic builds. Integration into projects involves including the primary header <event2/event.h> for core event handling functions. Applications link against the library using flags like -levent for the full library or -levent_core for core components only, as in gcc program.c -o program -levent. For cross-compilation to Windows from Unix hosts, with the generator (cmake -G "MinGW Makefiles" ..) supports building via , requiring a compatible toolchain and optional dependencies like configured with OPENSSL_ROOT_DIR. Static linking is preferred for portable executables, avoiding runtime DLL dependencies.

Adoption and Applications

Notable Software Using libevent

Libevent has been integrated into numerous prominent open-source projects, particularly those requiring efficient event-driven networking and I/O handling. In the domain of web and caching systems, , a high-performance object caching system, relies on libevent to manage scalable sockets and handle tens of thousands of concurrent connections across worker threads. For networking and security applications, , which implements for anonymous internet communication, utilizes libevent to manage events such as , sends, and receives within its . Similarly, , a lightweight client, incorporates libevent as a key dependency for its to facilitate efficient file transfers. The NTP package, responsible for synchronization, employs libevent in its SNTP component for event notification in client operations. In desktop environments and development tools, —the open-source foundation for —leverages libevent for its implementation on macOS and platforms, enabling responsive handling of and I/O events in the browser. , a similar to , depends on libevent for its core event processing to manage multiple terminal sessions efficiently.

Case Studies

, the anonymity , integrates libevent to manage event-driven I/O for its core operations, enabling efficient handling of thousands of concurrent circuits that route traffic through multiple relays. By leveraging libevent's event base and loop mechanisms, Tor dispatches callbacks for readability, writability, and timeouts across a large number of file descriptors without blocking, which is crucial for maintaining low in encrypted, multi-hop connections. On systems, Tor configures libevent to use the backend, which provides O(1) scalability for event notifications, allowing relays to process high volumes of circuit data—often exceeding 10,000 active circuits per node—while minimizing CPU overhead and ensuring portability across platforms. Memcached, a caching system, employs libevent to implement its single-threaded, , facilitating non-blocking I/O operations that support high-throughput access to cached items across thousands of concurrent client connections. Libevent's powers the worker threads, where each thread initializes its own event base to monitor socket events for incoming requests and responses, enabling Memcached to scale linearly with available cores while avoiding the overhead of context switching in multi-threaded models. For cache management, libevent timers are utilized in periodic tasks, such as updating the internal clock every second, though item expiration primarily occurs lazily upon access via least-recently-used (LRU) eviction rather than per-item timeouts, ensuring efficient memory usage without constant clock polling. Chromium, the open-source browser project, incorporates libevent as part of its message pump implementation on non-Windows platforms, creating a custom event base to unify handling of events (such as input and rendering updates) and network events (like socket I/O for web requests). This allows the browser's main to run an efficient that integrates libevent's abstractions with platform-specific APIs like or , processing asynchronous tasks without polling and supporting the high concurrency required for tab management and resource loading. By wrapping libevent in its base/message_pump_libevent component, achieves cross-platform consistency for event dispatching. TmUX, a , relies on libevent to orchestrate signal and socket events essential for non-blocking session management, allowing users to create, detach from, and reattach to multiple sessions seamlessly. Libevent's enables tmux to register events for Unix domain sockets used in client-server communication between the tmux daemon and client processes, as well as signals like SIGCHLD for monitoring and SIGWINCH for resizing, all processed within a single to prevent blocking during interactive operations. This setup supports efficient of panes and windows across remote connections, handling dynamic session state changes with minimal latency and resource use on systems.

Alternatives and Comparisons

libev

Libev is an event notification library for systems, designed as a high-performance alternative to libevent with a focus on simplicity and efficiency. Unlike libevent, which provides a more abstracted interface through its event_base structure for managing event loops, libev emphasizes a lighter-weight, single-threaded that avoids global variables in favor of explicit loop contexts, enabling better and reducing overhead from unnecessary abstractions. This design philosophy stems from libev's intent to rectify architectural decisions in libevent, such as reliance on globals, resulting in smaller watcher structures (e.g., 56 bytes for I/O watchers on x86_64 compared to libevent's 136 bytes). Libev's is simpler and more modular, modeling itself loosely after libevent but stripping away extras to concentrate solely on core event handling. Development of libev has been less active in recent years, with its last major release (4.33) in 2020. In terms of , a 2011 benchmark demonstrates libev's advantages in specific scenarios against libevent 1.4.3, particularly with backends like and , where its minimal overhead leads to significantly lower costs for event setup, changes, and dispatching. For instance, in tests with up to 100,000 file descriptors and idle timeouts, libev achieved polling times 2–3 times faster than libevent 1.4.3, with total execution times roughly half, due to optimized management and reduced friction. However, libevent has seen substantial improvements since (released in 2009), and no recent benchmarks confirm if these gaps persist as of 2025; developers should verify with current versions. Libevent offers superior cross-platform portability, including experimental support for Windows IOCP, whereas libev lacks native Windows integration and requires handle conversions, making libevent preferable for heterogeneous environments. Feature-wise, libev employs a watcher-based —such as I/O, , or signal watchers—each tied to a callback function, providing fine-grained control over events like wallclock s or monitoring, but it omits built-in utilities for higher-level protocols. In contrast to libevent's integrated HTTP server and DNS resolver, libev requires external add-ons (e.g., c-ares for asynchronous DNS) to handle such functionality, avoiding the bugs and complexities associated with libevent's bundled features like in HTTP streaming. This keeps libev leaner but demands more integration effort for advanced networking. Libev suits embedded systems or simple applications prioritizing raw speed and low resource use, such as terminal emulators like rxvt-unicode or lightweight servers, where its event loop efficiency shines without the bloat of extras. Libevent, conversely, is better for complex server environments needing out-of-the-box utilities like non-blocking I/O wrappers and protocol support, facilitating quicker development for multi-protocol applications.

libuv

Libuv, developed as the library powering , presents a distinct alternative to libevent in its approach to , emphasizing cross-platform consistency and broader system integrations. While libevent centers on a lightweight, event-centric model for handling I/O notifications on file descriptors and timeouts, libuv adopts a more structured paradigm built around handles and requests. Handles represent persistent objects, such as TCP connections or timers, that remain active within the , whereas requests manage transient operations like asynchronous writes or DNS lookups, allowing for a clearer separation of ongoing and one-off tasks. This handles-oriented design in libuv contrasts with libevent's unified event abstraction, where developers register callbacks directly for specific events (e.g., read or write readiness) without distinguishing between long- and short-lived entities, potentially simplifying simpler I/O scenarios but requiring more manual management in complex ones. In terms of performance and scalability, both libraries achieve high concurrency for network servers, supporting thousands of connections through efficient polling mechanisms like on or on BSD systems. However, libuv demonstrates particular strengths on Windows via its native integration with I/O Completion Ports (IOCP), enabling scalable asynchronous operations without the overhead seen in earlier libevent implementations that initially relied on select() before adding IOCP support in version 2.0. Libuv also incorporates a default for blocking operations, enhancing throughput for mixed workloads, whereas libevent offers multi-threading via optional locking or isolated event bases, which may introduce additional configuration complexity for similar results. Benchmarks indicate comparable dispatch efficiency in Unix environments, where libevent's maturity provides robust backend optimizations, but libuv's unified model often yields better resource efficiency in cross-platform deployments. Libuv extends beyond core I/O polling with built-in support for filesystem operations (e.g., asynchronous reads via its ), DNS resolution through requests, and TTY handling for terminal interactions, features not natively integrated in libevent's primary . These capabilities stem from libuv's evolution within , enabling seamless bridging to for web applications, unlike libevent's focus on pure C/C++ environments. For portability, both libraries compile across Unix variants, Windows, and other platforms, but libuv prioritizes a consistent abstraction, abstracting platform-specific details like IOCP or to minimize developer effort in multi-OS projects. Libuv remains actively maintained, with version 1.51.0 released in April 2025. Regarding ecosystems and use cases, libuv thrives in modern, cross-platform applications, serving as the foundation for runtime and extensions in languages like and (via uvloop), as well as influencing async runtimes in such as those building on its bindings. This integration fosters a vibrant around JavaScript and higher-level bindings, ideal for web servers and real-time apps requiring diverse I/O. In contrast, libevent remains a staple for performance-critical C/C++ servers, such as those in networking proxies or databases, where its event-centric simplicity and Unix backend maturity align with low-level, embeddable needs without broader system dependencies.

Release History

Major Versions

Libevent's major version releases have introduced significant architectural improvements, enhanced cross-platform compatibility, and new APIs to support evolving networking needs. Version 1.4, released on November 11, 2007, marked a stable milestone primarily for systems, incorporating the evhttp and evdns modules for HTTP and DNS handling, respectively, along with a new RPC subsystem for distributed client-server applications and comprehensive Doxygen-based documentation. The 2.0 series, first released on April 17, 2009, underwent a modular redesign to improve maintainability, introduced support for Windows I/O Completion Ports (IOCP) for efficient , and debuted the bufferevent for streamlined buffer management, establishing it as the first fully cross-platform stable version. Libevent 2.1, released on April 3, 2012, added support for monotonic timers to handle clock adjustments reliably, enhanced debugging tools for diagnostics, and expanded evbuffer capabilities with features like chained buffers and iovec integration, forming the basis of the current stable branch culminating in version 2.1.12 on July 5, 2020, which remains the latest stable release as of November 2025. The 2.2 alpha series began with version 2.2.1-alpha, released on May 21, 2023, and remains in ongoing as of November 2025, featuring optimizations across event backends and new for advanced event , with contributions from over 150 developers addressing modern demands.

Bug Fixes and Updates

The 1.4 branch of libevent received its final update in version 1.4.14b, released on June 7, 2010, which addressed several critical bugs including crashes during resolve.conf parsing and various memory management issues. This release also added support for building on Win32 with enabled, improving compatibility on Windows platforms. The 1.4 is now end-of-life, with no further or updates provided, as shifted to newer major versions. In the 2.0 branch, version .21-stable, released on November 18, 2012, focused on stability enhancements such as fixes for SSL-related issues and prevention of resource leaks in bufferevents and other components. These patches resolved potential hangs and memory inefficiencies observed in prior releases, particularly under high-load scenarios. The 2.0 branch has been superseded by the 2.1 series, with users encouraged to migrate for continued support. The 2.1 branch has seen ongoing maintenance through minor releases and patches. Version 2.1.11-stable, released on August 1, 2019, included fixes for an ABI breakage introduced in the previous version, along with adjustments to the shared object (SO) version to ensure compatibility. Subsequent patches in this branch addressed memory leaks, with version 2.1.12-stable (July 5, 2020) providing general bug fixes for evbuffer handling and other core components. A notable security issue, CVE-2024-31735, identified a memory leak in evbuffer_add_ functions of 2.1.12-stable that could lead to denial-of-service attacks; this was addressed in later builds and alpha releases. Maintenance continues via GitHub issue tracking for alpha developments, including the 2.2.1-alpha series, where additional fixes (e.g., in SSL structures and evbuffer_add_file) have been incorporated. Distribution-specific updates, such as those in and packaging, have kept the 2.1.12-stable version current through 2025, with builds like 2.1.12-stable-10build1 incorporating portability and build fixes.

References

  1. [1]
    libevent
    The libevent API provides a mechanism to execute a callback function when a specific event occurs on a file descriptor or after a timeout has been reached.Libevent Documentation · Fast portable non-blocking... · Older Releases
  2. [2]
    New Libevent Releases - Niels Provos
    Jul 29, 2009 · Nick just announced two new libevent releases. Here is his summary. Libevent 1.4.12-stable: You can find the source in the usual place.Missing: origin | Show results with:origin
  3. [3]
    Some notes on progress with IOCP and Libevent | The Tor Project
    Mar 1, 2009 · Libevent is a software library originally written by Niels Provos (then of UMichigan, now of Google), and now co-developed by Niels Provos and ...
  4. [4]
    libevent/libevent: Event notification library - GitHub
    For the latest released version of Libevent, see the official website at https://libevent.org/. There's a pretty good work-in-progress manual up.Libevent · Releases 20 · Issues 122 · Pull requests 20
  5. [5]
    Libevent 2.0.x: Like Libevent 1.4.x, Only More So.
    Jan 26, 2010 · So, we started using Niels Provos's Libevent library around 2005. It was around version 1.0 back then, and it had... a few bugs. To get our ...
  6. [6]
    Fast portable non-blocking network programming with Libevent
    - **Purpose**: Provides a fast, portable framework for non-blocking network programming using Libevent.
  7. [7]
    Google's Niels Provos battles malware on the Web - CNET
    Jan 19, 2011 · ... Provos wrote libevent, a software library released in 2000 that allows programmers to write scalable network programs. "He has written some ...
  8. [8]
  9. [9]
  10. [10]
  11. [11]
    libevent Documentation
    Libevent is an event notification library for developing scalable network servers, executing callbacks on file descriptors or timeouts, and supporting various ...Library Setup · Dispatching Events · I/o Buffers
  12. [12]
    libevent/LICENSE at master · libevent/libevent
    **Summary of Copyright Notice and Historical Information:**
  13. [13]
    Old releases - libevent
    Libevent 2.1.x · First alpha release in the 2.1. · Useful features for controlling the event loop and avoiding priority inversion · New debugging features. · New ...
  14. [14]
    Tor 0.1.0.10 is released - Archives
    Jun 14, 2005 · This release features cleanup on Windows, including making NT services work; many performance improvements, including libevent to use poll/epoll ...
  15. [15]
    Performance and Efficiency - Memcached Documentation
    Memcached uses libevent for scalable sockets, allowing it to easily handle tens of thousands of connections. Each worker thread on memcached runs its own event ...Missing: adoption Tor
  16. [16]
  17. [17]
    Working with events - libevent
    Libevent events represent conditions like file descriptors, timeouts, or signals. Events are created with `event_new()`, made pending with `event_add()`, and ...Inspecting Event Status · Manually Activating An Event · Optimizing Common Timeouts
  18. [18]
    event2/event.h File Reference - libevent
    Get the kernel signal handling mechanism used by Libevent. More ... event mechanisms. An application can make use of multiple event bases to ...
  19. [19]
    Creating an event_base - libevent
    Each event_base has a "method", or a backend that it uses to determine which events are ready. The recognized methods are: select. poll. epoll. kqueue. devpoll.Setting Up A Complicated... · Examining An Event_base's... · Setting Priorities On An...Missing: ports | Show results with:ports
  20. [20]
    event_config Struct Reference - libevent
    Configuration for an event_base. There are many options that can be used to alter the behavior and implementation of an event_base.Missing: backend detection
  21. [21]
    Bufferevents: concepts and basics - libevent
    A bufferevent that uses the Windows IOCP interface to send and receive data to an underlying stream socket. (Windows only; experimental.) filtering bufferevents.
  22. [22]
    event2/bufferevent.h File Reference - libevent
    A bufferevent that uses the openssl library to send and receive data over an encrypted connection. Created with bufferevent_openssl_socket_new() or ...Missing: utility components evhttp evrpc
  23. [23]
    Using DNS with Libevent: high and low-level functionality
    Libevent provides a few APIs to use for resolving DNS names, and a facility for implementing simple DNS servers.Non-Blocking Hostname... · Creating And Configuring An... · Initializing Evdns From The...Missing: asynchronous | Show results with:asynchronous
  24. [24]
    event2/dns.h File Reference - libevent
    Initialize the asynchronous DNS library. This function initializes support for non-blocking name resolution by calling evdns_resolv_conf_parse() on UNIX and ...Evdns_base_resolv_conf_parse... · Evdns_base_set_option() · Evdns_getaddrinfo()
  25. [25]
    Using the built-in HTTP server - libevent
    The main elements are the evhttp_set_gencb() function, which sets the callback function to be used when an HTTP request is received, and the ...Missing: framework | Show results with:framework
  26. [26]
    event2/http.h File Reference - libevent
    Adds a virtual host to the http server. A virtual host is a newly initialized evhttp object that has request callbacks set on it via evhttp_set_cb() or ...Missing: framework | Show results with:framework
  27. [27]
    event2/rpc.h File Reference - libevent
    This header files provides basic support for an RPC server and client. To support RPCs in a server, every supported RPC command needs to be defined and ...Missing: protocol | Show results with:protocol
  28. [28]
    Working with an event loop - libevent
    The event_base_loop() function runs an event_base until there are no more events registered in it. To run the loop, it repeatedly checks whether any of the ...Stopping The Loop · Re-Checking For Events · Running A Function Over...
  29. [29]
    Bufferevents: advanced topics - libevent
    This chapter describes some advanced features of Libevent's bufferevent implementation that aren't necessary for typical uses.
  30. [30]
    event2/thread.h File Reference - libevent
    When using a multi-threaded application in which multiple threads add and delete events from a single event base, Libevent needs to lock its data structures.
  31. [31]
    Setting up the Libevent library
    Detailed event debugging is a feature which can only be enabled at compile-time using the CFLAGS environment variable "-DUSE_DEBUG". With this flag enabled, any ...Memory Management · Locks And Threading · Detecting The Version Of...
  32. [32]
    evutil_monotonic_timer Struct Reference - libevent
    Detailed Description. Structure to hold information about a monotonic timer. Use this with evutil_configure_monotonic_time() and evutil_gettime_monotonic().
  33. [33]
    whatsnew-2.1.txt - GitHub
    Using monotonic timers makes Libevent more resilient to changes in the system time ... priority-inversion mechanisms in Libevent. To avoid starvation from ...Missing: tips | Show results with:tips
  34. [34]
    A tiny introduction to synchronous non-blocking IO - libevent
    A tiny introduction to synchronous non-blocking IO. These documents are Copyright (c) 2009-2012 by Nick Mathewson, and are made available under the Creative ...
  35. [35]
    platform/external/libevent - Git at Google - Android GoogleSource
    To build Libevent, type $ ./configure && make (If you got Libevent from the git repository, you will first need to run the included “autogen.sh” script.
  36. [36]
    iOS compilation · Issue #1775 · libevent/libevent - GitHub
    Jan 22, 2025 · When I try to compile my project in iOS I have an error from libevent not compiling for iOS. It works if I try to compile it for macOS.Missing: caveats | Show results with:caveats
  37. [37]
    libevent on QNX 6.5.0
    Sep 20, 2017 · libevent on QNX 6.5.0. To: pkgsrc-users%netbsd.org@localhost ... QNX 6.5.0 doesn't support SA_RESTART. This is not a fix, it's just a ...Missing: iOS | Show results with:iOS
  38. [38]
    libevent - Homebrew Formulae
    libevent is an asynchronous event library. It supports macOS on Apple Silicon and Intel, and Linux on ARM64 and x86_64. Current stable version is 2.1.12.
  39. [39]
    libevent/Documentation/Building.md at master · libevent/libevent
    Insufficient relevant content. The provided URL content is a GitHub page fragment with navigation and metadata, lacking specific details on libevent compilation, dependencies, packaging, or integration. No instructions or options (e.g., autotools, cmake, --disable-openssl, --enable-thread-support) are present.
  40. [40]
  41. [41]
  42. [42]
  43. [43]
  44. [44]
    libevent - vcpkg package
    vcpkg install libevent. In manifest mode, run the following vcpkg command in your project directory: vcpkg add port libevent. vcpkg. Get Started. Windows.Missing: apt yum conan
  45. [45]
    libevent - Conan 2.0: C and C++ Open Source Package Manager
    Conan is an open source, decentralized and multi-platform package manager for C and C++ that allows you to create and share all your native binaries.Missing: history | Show results with:history
  46. [46]
  47. [47]
    Data flow in the Tor process
    Under the hood, this functionality is implemented using libevent events: one for reading, one for writing. These events are turned on/off in main.c, in the ...
  48. [48]
  49. [49]
    [or-cvs] [tor/master] Turn on epoll changelists with libevent 2.0.9-rc ...
    Dec 16, 2010 · [or-cvs] [tor/master] Turn on epoll changelists with libevent 2.0.9-rc and later ; To: or-cvs@xxxxxxxxxxxxx ; From: nickm@xxxxxxxxxxxxxx ...
  50. [50]
    Understanding The Memcached Source Code — Event Driven I
    Jan 26, 2019 · The callback passed through is worker_libevent which essentially starts the event loop using event_base_loop , this time, on worker threads ...
  51. [51]
    Are there significant differences between the Chrome browser event ...
    Sep 9, 2014 · Node.js and Chrome do not use the same event loop implementation. Chrome/Chromium uses libevent, while node.js uses libuv.The implementaiton of event loop with Libuv or Libevent on v8, why ...build - I can't find in ../third_party/libevent/event-config.h path to ...More results from stackoverflow.com
  52. [52]
    GitHub - tmux/tmux: tmux source code
    ### Summary of tmux's Use of libevent for Signal and Socket Events in Session Management
  53. [53]
    Design overview - libuv documentation
    libuv provides users with 2 abstractions to work with, in combination with the event loop: handles and requests. Handles represent long-lived objects capable ...Missing: libevent | Show results with:libevent
  54. [54]
    Introduction - libuv documentation
    This 'book' is a small set of tutorials about using libuv as a high performance evented I/O library which offers the same API on Windows and Unix.
  55. [55]
    libuv/libuv: Cross-platform asynchronous I/O - GitHub
    libuv is a multi-platform support library with a focus on asynchronous I/O. It was primarily developed for use by Node.js, but it's also used by Luvit, Julia, ...
  56. [56]
    Libevent 2.1.12: changelog
    Jul 5, 2020 · Changes in version 2.1.12-stable (05 Jul 2020) This release contains mostly bug fixes (I decided not to port some features that can be ...
  57. [57]
    https://raw.githubusercontent.com/libevent/libeven...
    Changes in version 2.2.1-alpha (21 May 2023) Libevent 2.2.1-alpha includes a number of new features and performance improvements. The log below tries to ...
  58. [58]
    https://raw.githubusercontent.com/libevent/libeven...
    Changes in 1.4.14b-stable o Set the VERSION_INFO correctly for 1.4.14 ... Libevent 1.4 build on win32 with Unicode enabled. (bce58d6 Brodie Thiesfield) ...
  59. [59]
    ChangeLog - GitHub
    ... Libevent 2.0 (da70fa7 Arno Bakker) TESTS AND TEST FIXES: o Fix a race condition in the dns/bufferevent_connect_hostname test. (cba48c7) o Add function to ...
  60. [60]
    Releases · libevent/libevent - GitHub
    May 21, 2023 · Libevent 2.2.1-alpha includes a number of new features and performance improvements. The log below tries to organize them by rough area of effect.
  61. [61]
    Changelog for 2.1.11 version - libevent
    Changes in version 2.1.11-stable (01 Aug 2019) This release contains one ABI breakage fix (that had been introduced in 2.1.10, and strictly speaking this ...Missing: tips | Show results with:tips
  62. [62]
    CVE-2024-31735: LibEvent Library Memory Leak
    Jun 6, 2024 · Our research group found a memory leak in the LibEvent Library v2.1.12-stable that allows an attacker to cause a denial of service (DoS) via the evbuffer_add_ ...