Revision history for Linux-Event 0.105 2026-08-29 - Add query-driven Loop introspection through running, count, has, objects, inspect, census, resources, why_alive, and pressure. Optional profile, stats, and reset_stats expose native timing and counters without adding permanent managed-object bookkeeping to the dispatch hot path. - Add explicit Stream callback batching. Raw subclasses may coalesce reads with read_batch_bytes, while framed subclasses may select bounded on_messages arrays with message_batch_size. Partial batches flush at the current read-drain boundary and never wait for future input. - Avoid inactive Stream deadline bookkeeping during read-interest and write-queue transitions. Focused watcher-state benchmarks retain Loop as the sole epoll owner and document why no cross-extension watcher ABI was introduced. - Split the Stream XS implementation into separately compiled state, transport, callback, input, delivery, read, write, transition, and per-framer C units behind one private header and one unchanged extension. - Move Stream subclass declarations, option validation, callback resolution, and immutable descriptor caching into the private Linux::Event::Stream::_Descriptor module while retaining Stream.pm as the public connection-lifecycle implementation. - Keep the deliberately tiny deadline Timer type beside Stream lifecycle policy, avoiding a new public module or unnecessary implementation layer. - Make the Timer microbenchmark fall back from the high-resolution process CPU clock to Perl process times, and report CPU timing as unavailable instead of failing installation when neither clock advances. Record the selected clock source in benchmark JSON and cover the fallback path. - Report non-Linux platforms as OS unsupported during configuration so CPAN Testers classifies the intentionally Linux-only distribution as NA rather than UNKNOWN. Add regression coverage for the configuration guard. - Add GitHub Actions coverage for supported Perl versions, distribution construction, metadata, POD, and native source packaging; publish CI, license, Perl, CPAN, and Kwalitee badges and complete the async extension boundary documentation. Exclude MakeMaker backup files from generated source archives. 0.104 2026-08-28 - Make the performance-regression and Timer benchmark smoke tests portable to systems whose process CPU clock does not advance for extremely small workloads. The benchmarks still reject non-positive timing samples. - Publish complete META spec 2 repository, bugtracker, and public-module provider metadata, plus security and contribution policies. 0.103 2026-08-27 - Make raw Loop registration handles stable lifecycle tokens. Cancelled, replaced, and Loop-destroyed handles are now inert even after native watcher storage or file-descriptor numbers are reused, and retained Perl state is released as soon as dispatch safety permits. - Restore Loop driver state after callback exceptions, reject recursive driving of the same Loop, reject event-capacity changes during dispatch, let run_once ignore an old stop request, and correct idle run_for statistics. - Apply Stream's normal high/low-watermark contract to output queued before attachment or connection readiness, including pending-byte reporting and exactly one delayed on_drain notification after the transport is usable. - Set adopted Stream descriptors nonblocking and close-on-exec, install the native drain callback only when requested by the subclass, and make callback-driven close safe throughout readiness, transition, drain, EOF, and transport-error dispatch. - Close Process stdin after max_pending_stdin overflow before reporting the typed output_limit error, so an over-limit producer cannot continue feeding that pipe. - Release Wakeup owner state on cancellation and reject attachment of a terminal Wakeup. - Add regression coverage for registration reuse and dispatch recovery, Loop driver contracts, Stream pre-connect flow control, adopted descriptor flags, callback-close safety, Process stdin limits, Signal recovery, Wakeup lifecycle, and TLS protocol transitions with leftover input. - Remove private implementation layers without changing the public API: Listener now uses its XS implementation directly, Stream and Datagram share Linux::Event::_Resolver, and the tiny Stream deadline helper lives in Stream.pm. 0.102 2026-08-21 - Fix Linux::Event::Wakeup compilation on Perl builds without PERL_IMPLICIT_CONTEXT, including ordinary non-threaded Perl. Such builds now use the sole interpreter identity while threaded/multiplicity builds retain pointer-based interpreter ownership checks. - Add regression coverage for interpreter identity on both multiplicity and non-multiplicity Perl configurations. 0.101 2026-08-21 - Publish the completed API as a stable release and synchronize every bundled Perl and XS component at version 0.101. - Add Linux::Event::Wakeup, a subclass-defined eventfd boundary with coalesced Loop-thread callbacks, safe fork signalling, and per-ithread descriptor duplication that keeps callbacks and data owner-confined. - Add production Stream socket policy at class and construction time: local address/port binding, TCP_NODELAY, keepalive tuning, TCP_USER_TIMEOUT in seconds, send/receive buffers, SO_BINDTODEVICE, live getters/setters, and a cached configure_socket hook. - Apply Stream socket policy before outbound bind/connect and before accepted or adopted transport attachment; expose local addresses and report family/configuration failures as structured Error values. - Extend the private asynchronous resolver with SOCK_DGRAM requests while preserving its typed native completion queue and cancellation model. - Add Linux::Event::Datagram for connected and unconnected UDP and Unix datagrams, native recvmsg/sendto packet I/O, lazy peer Addresses, whole- packet queues, soft backpressure, hard byte/packet limits, truncation detection, socket policy, ownership, detach, and Unix-path cleanup. - Add Linux::Event::Process using posix_spawnp, pidfd_open, waitid(P_PIDFD), and pidfd_send_signal, with asynchronous pipe stdio, decoded exit status, replacement environments, cwd support, SIGPIPE-safe stdin, atomic close-on-exec pipes, child-side closure of caller stdio source descriptors, deterministic final output draining, and partial-failure cleanup. - Make native resource objects interpreter-owned and non-clonable except for Wakeup's deliberately restricted signalling handle; rebuild cached native class descriptors lazily in a child ithread and reject stale Wakeup handles round-tripped from a worker interpreter. - Complete API, lifecycle, failure, ownership, thread/fork, local-binding, Datagram, and Process regression tests, including callback-exception and descriptor-reuse safety cases. - Add focused Wakeup, Datagram, and Process examples and microbenchmarks; update architecture, lifecycle, transport, roadmap, and module POD around the completed public surface with concrete annotated examples. - Harden distribution configuration for Linux, required libc/OpenSSL capabilities, CPAN metadata, manifest coverage, and clean distribution testing. 0.100_030 2026-08-21 - Make TLS declarative Stream policy: use Linux::Event::TLS on a Stream subclass and let connect or Listener acceptance select the client or server handshake role automatically. - Default outbound TLS server_name, SNI, and hostname verification to the connect host while retaining an explicit override for different service identities and adopted handles. - Load and validate accepted TLS certificate and key policy during Listener construction and create fresh native server state for every connection. - Pass Listener data automatically to each accepted Stream and remove the cumbersome accepted_stream_options hook from the public design. - Expose negotiated ALPN, protocol, cipher, and native TLS statistics directly on Stream without requiring access to its internal provider. - Add declaration validation, inheritance, role, callback-order, metadata, and integrated client/server regression coverage; update all current Listener, Stream, connection, and transport documentation to one model. 0.100_029 2026-08-21 - Add optional Listener on_accept($listener, $stream) after Stream construction and Loop attachment, before plain Stream readiness or TLS handshake completion. - Contain on_accept exceptions by closing only the affected Stream, suppressing its pending on_ready, and delivering a nonfatal callback Error through the Listener's on_error policy. - Make Listener family reporting consistent with Address: family returns inet, inet6, unix, or unknown; family_number retains the native value; is_tcp and is_unix provide convenience predicates. - Replace undefined Listener documentation placeholders with complete TCP, Unix, and adopted-socket examples annotated as required, default, or optional. - Add plain and TLS callback-order coverage plus callback-failure cleanup and family-accessor regression tests. 0.100_028 2026-08-21 - Correct inbound acquisition ownership: remove the accidental MyStream->listen() proxy and make Linux::Event::Listener->new with an explicit stream_class the sole Listener construction API. - Move runtime Listener error policy off Stream classes. The base Listener remains fatal; applications may override on_error in a Listener subclass. - Add established Stream idle, read, and write inactivity deadlines with cached subclass defaults and per-connection constructor overrides. - Add constructor and runtime overall-operation deadlines through deadline, set_deadline(), clear_deadline(), and monotonic after/at forms. - Start established deadlines only after plain or TLS transport readiness, leaving resolver, connection, TLS handshake, and TLS shutdown deadline ownership unchanged. - Track successful read and write progress natively only for Streams that enable inactivity policy; ordinary Streams perform no activity clock reads in their I/O path. - Use at most one private Timer per deadline-enabled Stream, sharing the Loop's existing timerfd and native deadline heap without exposing the internal Timer object. - Deliver typed timeout errors with operation, duration, and absolute deadline context, then follow ordinary on_error/on_close cleanup. - Add plain, TLS, transition, pause/resume, EOF, queued-write, lifecycle, validation, and benchmark regression coverage. 0.100_027 2026-08-21 - Move hostname resolution off the reactor thread into a private XS resolver with two lazy native pthread workers per Loop. - Deliver copied getaddrinfo results through one eventfd watched by the ordinary raw Loop API; no public eventfd, post, or threaded-Perl API is introduced. - Interleave IPv6 and IPv4 candidates, stagger pending attempts by 250 ms, transfer the first successful socket, and deterministically close losers. - Make cancellation discard late completion safely, include DNS in the connection deadline, retain literal-address bypass, and document that processes must fork before starting resolver workers. - Add native delivery, cancellation, hostname connection, ordering, and resolver microbenchmark coverage. - Add subclass-defined Linux::Event::Signal with one lazy signalfd and native fan-out registry per Loop, supporting several signals per object and several objects per signal. - Aggregate complete signalfd drains before callback delivery, preserve attachment-order fan-out, and make self/cross-cancellation callback-safe. - Track signal-mask ownership exactly, reject cross-Loop consumption of one signal number, restore only Loop-owned entries, and make resolver workers block signals independently. - Add Signal API, delivery, lifecycle, mask, error, and benchmark coverage plus explicit thread and fork ownership documentation. 0.100_026 2026-08-21 - Add Linux::Event::Timer as an abstract subclass-defined public object with cached on_timer callbacks and the same Loop->add attachment contract as Stream and Listener. - Support relative, absolute monotonic, and fixed-rate recurring schedules, including distinct first deadlines, in-callback rescheduling, and idempotent terminal cancellation. - Give each Loop one lazy timerfd and one indexed native minimum heap for every active Timer, with FIFO equal-deadline order and nanosecond internal deadlines. - Coalesce missed recurring ticks, retain fixed-rate phase, bound callback batches for descriptor fairness, and defer zero-delay callbacks to a later Loop turn. - Define deterministic ownership and cleanup: Loop retains active Timers; final expiration, cancellation, and Loop destruction release application data safely, including cancellation during a callback. - Extend statistics, lifecycle/API/scheduling tests, the release regression contract, and a dedicated scaling benchmark for Timer lifecycle, rescheduling, and expiration delivery. 0.100_025 2026-08-21 - Simplify the public hierarchy to Linux::Event::Loop, Stream, Listener, TLS, Framer, Error, and Address. Remove the public Watcher, IO, Connect, Connector, Listen, XSLoop, and XSWatcher compatibility modules. - Make MyStream->connect() the sole public outbound acquisition API and retain one Stream identity across connection, optional TLS readiness, established I/O, and close. Keep the acquisition engine private. - Make MyStream->listen() the normal inbound API and keep accept mechanics in a private Listener engine. Accepted descriptors become the configured Stream subclass directly, without a temporary public registration. - Support both loop => $loop construction and detached construction plus Loop->add() for Stream and Listener. Both forms attach the same object; add() sets its Loop and returns it. - Return only an opaque native registration from the low-level watch API; raw registrations are not a named public class hierarchy. - Consolidate errors under Linux::Event::Error, peer addresses under Linux::Event::Address, and native framing declarations under Linux::Event::Framer::*. - Rewrite the module POD, README, lifecycle, connection, Listener, core, architecture, and benchmark documentation around the reduced API. - Replace obsolete Connect/Listen benchmark modes with raw baselines and direct comparisons of loop => and Loop->add() attachment styles. - Add a permanent capture/compare performance-regression suite covering reactor registration, Stream lifecycle and throughput, native delimiter framing, and integrated connect/listen acquisition. - Align active XS source and build names with the reduced public model and remove stale XSLoop/XSWatcher terminology from the reactor source. 0.100_024 2026-08-16 - Introduce Linux::Event::Watcher as the public lifecycle contract and Linux::Event::Loop as the canonical XS-first loop name. - Add Loop->add() for detached high-level Watchers while retaining watch() as the immediate raw-IO registration convenience. - Return Linux::Event::IO objects from raw watch/watch_fd registration; XSWatcher remains their compatibility native-method base. - Make Stream, Connect, and Listen Watchers with detached construction and temporary loop-constructor compatibility. - Add MyStream->connect(), preserving one Stream identity through outbound connection, optional verified TLS negotiation, established I/O, and terminal close. Writes before readiness use the bounded Stream queue. - Add MyStream->listen() and Linux::Event::Listener, which construct and attach accepted Stream subclasses without application socket plumbing. - Add the noun-named Connector and Listener error/peer public aliases while retaining Connect and Listen as advanced compatibility layers. - Expand lifecycle tests through automatic plain and TLS client/server paths, strict Watcher attachment, raw IO typing, and stable identity. - Harden the Connect lifecycle benchmark with balanced order, abortive teardown, configurable deadlines, correctness checks, and JSON output; add integrated Stream and automatic Listener comparison rows. 0.100_023 2026-08-16 - Split the Listen benchmark's previous manual-to-raw gap with a handoff row that constructs the same Perl filehandle and lazy Peer representation without invoking Listen control or subclass callback machinery. - Remove an avoidable array shift from Listen's accepted-batch traversal. - Use eight rotating repeats by default so all four benchmark modes occupy every execution position equally. 0.100_022 2026-08-16 - Use equal abortive client teardown in every Listen benchmark mode so large matrices do not exhaust ephemeral ports through TIME_WAIT buildup. The complete default 540,000-connection matrix now runs without later rows failing from state accumulated by earlier rows. 0.100_021 2026-08-16 - Add a manual XSLoop/native-accept baseline to the permanent Listen lifecycle benchmark, separating Listen handoff cost from Stream cost. - Rotate benchmark mode order across repeats to reduce execution-order bias and print the tested Linux::Event version in the report. - Replace the overly aggressive hardcoded two-second connection deadline with a configurable --timeout option that defaults to 30 seconds. 0.100_020 2026-08-16 - Add Linux::Event::Listen as the inbound stream-socket acquisition layer. - Create TCP and Unix listeners or adopt an existing listening handle. - Drain accept4 in XS with atomic nonblocking and close-on-exec flags. - Add bounded level-triggered accept fairness and safe edge-trigger rules. - Add lazy peer addresses, typed failures, resource-error pause/recovery, ownership-aware close/detach behavior, and direct Stream handoff. - Add a runnable line-delimited echo server and permanent Listen lifecycle microbenchmark under the distribution examples and bench directories. - Recover from watched descriptor-number reuse by falling back from epoll MOD/ENOENT to ADD during same-fd watcher replacement. 0.100_019 2026-08-15 - Merge a redesigned Linux::Event::Connect into the main distribution. Concrete subclasses define cached on_connect and on_error methods while each request stores only target, lifecycle, and application data. - Transfer a generic connected nonblocking filehandle rather than requiring or constructing Linux::Event::Stream. Stream, TLS, raw watchers, and specialized protocol engines remain independent consumers. - Add typed Linux::Event::Connect::Error failures, a default 10-second connection deadline, silent idempotent cancellation, strict address-mode validation, and loop-dispatched callbacks for immediate outcomes. - Create sockets atomically with SOCK_NONBLOCK and SOCK_CLOEXEC. A small native timerfd helper supplies connection deadlines and deferred terminal delivery while candidate policy remains in the cold Perl control path. - Replace same-fd watchers through one EPOLL_CTL_MOD instead of DEL plus ADD. Old watcher handles remain inert, so Connect can hand a socket to Stream during on_connect and safely cancel only its original registration. - Retain synchronous getaddrinfo and sequential fallback as documented initial limitations. The public contract and internal attempt collection are prepared for a later asynchronous Resolver and Happy Eyeballs. 0.100_018 2026-08-15 - Prevent OpenSSL socket writes from delivering SIGPIPE when a TLS peer closes abruptly. The TLS extension now uses a non-owning custom socket BIO whose writes use Linux MSG_NOSIGNAL. - Preserve application signal policy: TLS does not install a process-wide SIGPIPE handler or add per-operation signal-mask syscalls. 0.100_017 2026-08-15 - Merge Linux::Event::TLS into the Linux-Event distribution so the reactor, Stream, and OpenSSL transport build and test with one top-level command. - Keep TLS in its own native extension and preserve Stream's specialized plain fast path; plain operations still make no OpenSSL calls. - Remove the duplicate transport ABI header and build the TLS provider against the canonical header owned by XSStream. - Move TLS integration, deadline, EOF, and certificate fixtures into the main test suite and simplify the TLS microbenchmark to use one blib tree. - Add an OpenSSL 1.1.1 configuration probe with a direct diagnostic for missing development headers or libraries. 0.100_016 2026-08-15 - Add generic cold-path transport lifecycle hooks used by adjacent providers to install, disarm, reuse, and destroy deadline watchers. - Preserve Stream/XSLoop layering: the core still knows no OpenSSL policy, while transport timeout failures use the existing typed error lifecycle. - Keep ordinary plain Streams free of auxiliary watchers and provider-hook calls in their read/write syscall paths. - Add the permanent top-level run-tls-microbench.pl same-Stream comparison for specialized plain and adjacent OpenSSL transports. 0.100_015 2026-08-15 - Publish transport => $provider construction for established descriptors through an exact-version native Stream transport ABI. - Retain provider lifetime in XS and coordinate cross-direction readiness for nonblocking handshakes, reads, writes, and transport shutdown. - Add transport(), is_transport_ready(), and the optional cached on_transport_ready callback while preserving the specialized plain path. - Reject detach() for non-plain transports because an encrypted descriptor cannot safely be returned as an application plaintext handle. - Support the adjacent Linux::Event::TLS OpenSSL provider without adding an OpenSSL dependency to the Linux-Event distribution. 0.100_014 2026-08-15 - Introduce an internal native transport operation contract beneath Stream buffering, framing, backpressure, and lifecycle semantics. - Route read, write, writev queue draining, retry classification, errors, EOF, and writable shutdown through the connection's transport provider. - Keep the ordinary plain-fd provider on a specialized direct-syscall path with no Perl callback or indirect function call per syscall. - Distinguish WANT_READ and WANT_WRITE in the native result contract for a future nonblocking OpenSSL provider. - Add transport_name(), plain-provider contract tests, regression benchmark coverage, and a detailed TLS/provider/STARTTLS boundary specification. 0.100_013 2026-08-14 - Add the optional class-level max_pending_bytes safety limit while keeping the existing high/low-watermark write() return contract unchanged. - Enforce the bound in XS before allocating an unsent queue segment, so the native pending-output queue never grows beyond its configured limit. - Report overflow as a typed output_limit Stream error with attempted pending_bytes and limit details, invoke on_error, and close the Stream. - Reject protocol transitions atomically when existing queued output exceeds the target class's nonzero max_pending_bytes policy. - Add deterministic output-limit tests, native overflow instrumentation, documentation, and capped/uncapped Stream transport benchmark rows. 0.100_012 2026-08-14 - Add in-place Stream protocol transitions through transition_to(). A live connection may change to another Stream subclass without replacing its filehandle, watcher, XSState, output queue, lifecycle, or application data. - Preserve unread native input across raw/framed protocol boundaries and accept an explicit raw-callback suffix through input => $bytes. - Stop the old native parser immediately after an input callback changes descriptors, then reinterpret remaining bytes with the new descriptor without waiting for another readiness event. - Make transition validation atomic, including target max_buffer checks, and retain pause, EOF, backpressure, queued-output, and instrumentation state. - Add transition contract tests, native transition counters, a dedicated transition benchmark, benchmark smoke coverage, and protocol-upgrade docs. 0.100_011 2026-08-14 - Redesign Linux::Event::Stream as a subclass-defined API. Callbacks, framing, and transport policy are class behavior; constructor state is limited to loop, fh, and optional per-connection data. - Resolve callbacks and framer/transport configuration once per concrete subclass into a shared immutable XS descriptor, with independent mutable parser and queue state for every connection. - Replace the framer factory and per-connection framer objects with declarative `use Linux::Event::Stream::Framer 'Name', @args` syntax. Exact package-name resolution removes the duplicate keyword registry. - Remove the arbitrary custom-framer object contract and Linux::Event::Stream::Framer::Buffer. Application-specific protocols now parse raw on_data bytes; generally useful families remain native built-ins. - Add cached class-level stream_options for read size, watermarks, and framed-buffer limits. - Rewrite Stream/framer tests, benchmarks, POD, guides, architecture notes, metadata, and examples for the canonical subclass-descriptor model. 0.100_010 2026-08-14 - Add the versioned Stream lifecycle and retained-memory benchmark used to capture the object-configured contract-1 baseline before the API redesign. 0.100_009 2026-08-13 - Add native inbound ASCII DecimalLength framing for wire forms such as RFC 6587 octet-counted syslog: "5 HELLO". - Support one configurable non-digit separator, include_prefix, max_frame, shared definitions, Perl fallback, and Perl outbound frame()/send(). - Reject invalid, overlong, overflowing, and non-canonical decimal lengths. - Extend native-framer tests, benchmarks, and the framer-selection guide. 0.100_008 2026-08-13 - Add canonical unsigned LEB128 Varint framing with native inbound parsing. - Preserve Perl outbound frame() compatibility and the custom-framer fallback. - Reject overflowing, overlong, and non-canonical Varint prefixes. - Extend native-framer benchmarks and simplify the framer-selection guide. 0.100_007 2026-08-13 - Add named Loop watch(fh => ...) and watch(fd => ...) construction. - Add Linux::Event::Stream::Framer factory methods for built-in framers. - Document and test safe reuse of built-in framer definitions across Streams. - Keep watch_fd and concrete Framer::* constructors available for low-level and subclass use. 0.100_006 2026-08-13 - Merge Linux::Event::Stream into the main Linux::Event distribution. - Build Linux::Event::XSLoop and Linux::Event::Stream native extensions from one source distribution and one top-level build/test/install workflow. - Keep the raw reactor and high-level Stream APIs as separate namespaces. - Unify development package versions for the merged native ABI snapshot. - Add a novice-oriented framer-selection guide in Markdown and POD. - Preserve native Delimiter, Fixed, LengthPrefix, U32BE, and Netstring framing plus the custom native-backed Buffer plug-in path. - Preserve the reactor, Stream, framing, and native-framer benchmark tools.