Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
* Remove cells_frees duplicate storage from Frame Cell/free variable objects were stored in both a separate `Box<[PyCellRef]>` (cells_frees field) and in the localsplus fastlocals array. Remove the redundant cells_frees field and access cell objects directly through localsplus, eliminating one Box allocation and N clone operations per frame creation. * Extract InterpreterFrame from Frame with Deref wrapper Introduce InterpreterFrame struct containing all execution state fields previously on Frame. Frame now wraps InterpreterFrame via FrameUnsafeCell and implements Deref for transparent field access. localsplus and prev_line are plain fields on InterpreterFrame (no longer individually wrapped in FrameUnsafeCell) since the entire InterpreterFrame is wrapped at the Frame level. * Auto-format: cargo fmt --all --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* Fold const bool with unary not * Fold unnecessary TO_BOOL
Bumps [aws-lc-fips-sys](https://github.com/aws/aws-lc-rs) from 0.13.11 to 0.13.12. - [Release notes](https://github.com/aws/aws-lc-rs/releases) - [Commits](https://github.com/aws/aws-lc-rs/commits/aws-lc-fips-sys/v0.13.12) --- updated-dependencies: - dependency-name: aws-lc-fips-sys dependency-version: 0.13.12 dependency-type: indirect ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…7359) * vm: align specialization guards with CPython patterns * vm: tighten call specialization runtime guards * vm: add send_none fastpath for generator specialization * vm: restrict method-descriptor specialization to methods * vm: deopt call specializations on guard misses * vm: match CPython send/for-iter closed-frame guards * vm: restrict len/isinstance specialization to builtins * vm: use exact-type guards for call specializations * vm: align class-call specialization flow with CPython * vm: prefer FAST call opcodes for positional builtin calls * vm: add callable identity guard to CALL_LIST_APPEND * vm: make CALL_LIST_APPEND runtime guard pointer-based * vm: align call guard cache and fallback behavior with CPython * vm: use base vectorcall fallback for EXIT-style call misses * vm: simplify CALL_LEN/CALL_ISINSTANCE runtime guards * vm: infer call-convention flags for CPython-style CALL specialization * vm: check use_tracing in eval_frame_active, add SendGen send_none - Implement specialization_eval_frame_active to check vm.use_tracing so specializations are skipped when tracing/profiling is active - Add send_none fastpath in SendGen handler for the common None case
…ustPython#7350) * Implement locale-aware 'n' format specifier for int, float, complex Add LocaleInfo struct and locale-aware formatting methods to FormatSpec. The 'n' format type now reads thousands_sep, decimal_point, and grouping from C localeconv() and applies proper locale-based number grouping. Remove @unittest.skip from test_format.test_locale. * Fix complex 'n' format and remove locale expectedFailure markers Rewrite format_complex_locale to reuse format_complex_re_im, matching formatter_unicode.c: add_parens=0 and skip_re=0 for 'n' type. Remove @expectedfailure from test_float__format__locale and test_int__format__locale in test_types.py. * Auto-format: cargo fmt --all --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* Object header slimming: prefix allocation for ObjExt Extract dict, weak_list, and slots fields from PyInner<T> into a separate ObjExt struct allocated as a prefix before PyInner using Layout::extend(). Objects that don't need these fields (int, str, float, list, tuple, dict, etc.) skip the prefix entirely. - Add HAS_WEAKREF flag to PyTypeFlags for per-type weakref control - Add HAS_EXT bit to GcBits indicating prefix presence - Define ObjExt struct with dict, weak_list, slots - Shrink PyInner header from ~80-88 bytes to ~32 bytes for lightweight objects - Update all accessor methods to go through ext_ref() - Update bootstrap type hierarchy to use prefix allocation - Add __weakref__ getset descriptor for heap types - Set HAS_WEAKREF on builtin types that support weak references - Remove test_weak_keyed_bad_delitem expectedFailure (now passes) * Add HAS_WEAKREF to _asyncio Future/Task, rename weakref helpers - Add HAS_WEAKREF flag to PyFuture and PyTask (matches CPython) - Rename subtype_getweakref/setweakref to subtype_get_weakref/set_weakref to fix cspell unknown word lint * Add HAS_WEAKREF to array, deque, _grouper; remove expectedFailure markers - Add HAS_WEAKREF to PyArray and PyDeque (matches CPython) - Add HAS_WEAKREF to PyItertoolsGrouper (internal use by groupby) - Remove 6 expectedFailure markers from test_dataclasses for weakref/slots tests that now pass * Add HAS_WEAKREF to code, union, partial, lock, IO, mmap, sre, sqlite3, typevar types Add HAS_WEAKREF flag to built-in types that support weakref: - PyCode, PyUnion, PyPartial, Lock, RLock - All IO base/concrete classes (_IOBase, _RawIOBase, _BufferedIOBase, _TextIOBase, BufferedReader, BufferedWriter, BufferedRandom, BufferedRWPair, TextIOWrapper, StringIO, BytesIO, FileIO, WindowsConsoleIO) - PyMmap, sre Pattern, sqlite3 Connection/Cursor - TypeVar, ParamSpec, ParamSpecArgs, ParamSpecKwargs, TypeVarTuple Remove 3 expectedFailure markers from test_descr for now-passing tests. * Add HAS_DICT to type flags and handle non-METHOD/CLASS in descr_get - Add HAS_DICT flag to PyType (type metaclass) alongside existing HAS_WEAKREF. All type objects are instances of type and need dict support, matching CPython's PyType_Type. - Replace unimplemented!() in PyMethodDescriptor::descr_get with fallback to bind obj directly, matching CPython's method_get which uses PyCFunction_NewEx for non-METH_METHOD methods. * Fix ext detection, HeapMethodDef ownership, WASM error - Remove HAS_EXT gc_bits flag; detect ext from type flags using raw pointer reads to avoid Stacked Borrows violations - Store HeapMethodDef owner in payload instead of dict hack - Clear dict entries in gc_clear_raw to break cycles - Add WASM error fallback when exception serialization fails
* Suspend Python threads before fork()
Add stop-the-world thread suspension around fork() to prevent
deadlocks from locks held by dead parent threads in the child.
- Thread states: DETACHED / ATTACHED / SUSPENDED with atomic CAS
transitions matching _PyThreadState_{Attach,Detach,Suspend}
- stop_the_world / start_the_world: park all non-requester threads
before fork, resume after (parent) or reset (child)
- allow_threads (Py_BEGIN/END_ALLOW_THREADS): detach around blocking
syscalls (os.read/write, waitpid, Lock.acquire, time.sleep) so
stop_the_world can force-park via CAS
- Acquire/release import lock around fork lifecycle
- zero_reinit_after_fork: generic lock reset for parking_lot types
- gc_clear_raw: detach dict instead of clearing entries
- Lock-free double-check for descriptor cache reads (no read-side
seqlock); write-side seqlock retained for writer serialization
- fork() returns PyResult, checks PythonFinalizationError, calls
sys.audit
…thon#7376) * `--features` flag can take multiple values * Simplify CI job * Remove bad default * Enable jit on macOS
Bumps [rustls](https://github.com/rustls/rustls) from 0.23.36 to 0.23.37. - [Release notes](https://github.com/rustls/rustls/releases) - [Changelog](https://github.com/rustls/rustls/blob/main/CHANGELOG.md) - [Commits](rustls/rustls@v/0.23.36...v/0.23.37) --- updated-dependencies: - dependency-name: rustls dependency-version: 0.23.37 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Remove unnecessary `to_{owned,string}()` calls (RustPython#7367)
* Fix error message in ctype
Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.21.0 to 1.22.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](uuid-rs/uuid@v1.21.0...v1.22.0) --- updated-dependencies: - dependency-name: uuid dependency-version: 1.22.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Add `install-macos-deps` action * Use new action
On Windows, SimpleQueue skips write locking because pipe writes are assumed atomic. Without GIL, PipeConnection. _send_bytes races on _send_ov when multiple threads call send_bytes concurrently (e.g. _terminate_pool vs workers). Wait for pending overlapped writes inside WriteFile before returning to Python, so ERROR_IO_PENDING is never exposed and the _send_ov assignment window is negligible.
* apply more allow_threads * Simplify STW thread state transitions - Fix park_detached_threads: successful CAS no longer sets all_suspended=false, avoiding unnecessary polling rounds - Replace park_timeout(50µs) with park() in wait_while_suspended - Remove redundant self-suspension in attach_thread and detach_thread; the STW controller handles DETACHED→SUSPENDED via park_detached_threads - Add double-check under mutex before condvar wait to prevent lost wakes - Remove dead stats_detach_wait_yields field and add_detach_wait_yields * Representable for ThreadHandle * Set ThreadHandle state to Running in parent thread after spawn Like CPython's ThreadHandle_start, set RUNNING state in the parent thread immediately after spawn() succeeds, rather than in the child. This eliminates a race where join() could see Starting state if called before the child thread executes. Also reverts the macOS skip for test_start_new_thread_failed since the root cause is fixed. * Set ThreadHandle state to Running in parent thread after spawn * Add debug_assert for thread state in start_the_world * Unskip now-passing test_get_event_loop_thread and test_start_new_thread_at_finalization * Wrap IO locks and file ops in allow_threads Add lock_wrapped to ThreadMutex for detaching thread state while waiting on contended locks. Use it for buffered and text IO locks. Wrap FileIO read/write in allow_threads via crt_fd to prevent STW hangs on blocking file operations. * Use std::sync for thread start/ready events Replace parking_lot Mutex/Condvar with std::sync (pthread-based) for started_event and handle_ready_event. This prevents hangs in forked children where parking_lot's global HASHTABLE may be corrupted.
* vm: align CALL/CALL_KW specialization core guards with CPython * vm: keep specialization hot on misses and add heaptype getitem parity * vm: align call-alloc/getitem cache guards and call fastpath ordering * vm: align BINARY_OP, STORE_SUBSCR, UNPACK_SEQUENCE specialization guards * vm: finalize unicode/subscr specialization parity and regressions * vm: finalize specialization GC safety, tests, and cleanup
…tPython#7384) The method cache (TYPE_CACHE) was storing strong references (Arc clones) to cached attribute values, which inflated sys.getrefcount(). This caused intermittent test_memoryview failures where refcount assertions would fail depending on GC collection timing. Store borrowed raw pointers instead. Safety is guaranteed because: - type_cache_clear() nullifies all entries during GC collection, before the collector breaks cycles - type_cache_clear_version() nullifies entries when a type is modified, before the source dict entry is removed - Readers use try_to_owned_from_ptr (safe_inc) to atomically validate and increment the refcount on cache hit
- Remove weak_list from ObjExt, allocate WeakRefList as its own prefix slot before PyInner - Add MANAGED_WEAKREF flag (1 << 3) to PyTypeFlags - Normalize MANAGED_WEAKREF from HAS_WEAKREF after flag assembly - Use Layout::extend offsets in bootstrap allocator
…hon#7271) * Introduce TimeoutSeconds utility type for timeout parameters Follow-up refactoring from RustPython#7237. Python timeout parameters typically accept both float and int. Several places in the codebase used Either<f64, i64> for this, each repeating the same match-and-convert boilerplate. This extracts that into a TimeoutSeconds type in vm::function::number. Refactored sites: - _sqlite3::ConnectArgs.timeout - _thread::AcquireArgs.timeout - _thread::ThreadHandle::join timeout Either<f64, i64> in time.rs (6 sites) left unchanged: those are timestamp values with per-branch logic (floor, range checks, etc). Either<f64, isize> in select.rs also left unchanged (different type). * Validate timeout in ThreadHandle::join to prevent panic * refactor: move TimeoutSeconds from number to time module
* Newtype ConstIdx, Constants * Set generic
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] lib: cpython/Lib/locale.py dependencies:
dependent tests: (96 tests)
[x] lib: cpython/Lib/modulefinder.py dependencies:
dependent tests: (2 tests)
[x] lib: cpython/Lib/poplib.py dependencies:
dependent tests: (1 tests)
[ ] lib: cpython/Lib/asyncio dependencies:
dependent tests: (7 tests)
[x] test: cpython/Lib/test/test_builtin.py (TODO: 19) dependencies: dependent tests: (no tests depend on builtin) [ ] lib: cpython/Lib/concurrent dependencies:
dependent tests: (16 tests)
[x] lib: cpython/Lib/dataclasses.py dependencies:
dependent tests: (90 tests)
[ ] test: cpython/Lib/test/test_descr.py (TODO: 44) dependencies: dependent tests: (no tests depend on descr) [x] test: cpython/Lib/test/test_fork1.py dependencies: dependent tests: (no tests depend on fork1) [x] test: cpython/Lib/test/test_format.py (TODO: 6) dependencies: dependent tests: (no tests depend on format) [ ] test: cpython/Lib/test/test_gc.py (TODO: 2) dependencies: dependent tests: (169 tests)
[ ] test: cpython/Lib/test/test_generators.py (TODO: 14) dependencies: dependent tests: (no tests depend on generator) [ ] lib: cpython/Lib/multiprocessing dependencies:
dependent tests: (11 tests)
[x] lib: cpython/Lib/os.py dependencies:
dependent tests: (170 tests)
[x] lib: cpython/Lib/symtable.py dependencies:
dependent tests: (2 tests)
[x] lib: cpython/Lib/tabnanny.py dependencies:
dependent tests: (1 tests)
[x] lib: cpython/Lib/threading.py dependencies:
dependent tests: (150 tests)
[x] lib: cpython/Lib/tokenize.py dependencies:
dependent tests: (135 tests)
[x] lib: cpython/Lib/types.py dependencies:
dependent tests: (52 tests)
[x] lib: cpython/Lib/weakref.py dependencies:
dependent tests: (205 tests)
Legend:
|
Bumps [socket2](https://github.com/rust-lang/socket2) from 0.6.2 to 0.6.3. - [Release notes](https://github.com/rust-lang/socket2/releases) - [Changelog](https://github.com/rust-lang/socket2/blob/master/CHANGELOG.md) - [Commits](rust-lang/socket2@v0.6.2...v0.6.3) --- updated-dependencies: - dependency-name: socket2 dependency-version: 0.6.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…et (RustPython#7354) * gc: add CollectResult, stats fields, get_referrers, and fix count reset - Add CollectResult struct with collected/uncollectable/candidates/duration - Add candidates and duration fields to GcStats and gc.get_stats() - Pass CollectResult to gc.callbacks info dict - Reset generation counts for all collected generations (0..=N) - Return 0 for third value in gc.get_threshold() (3.13+) - Implement gc.get_referrers() by scanning all tracked objects - Add DEBUG_COLLECTABLE output for collectable objects - Update test_gc.py to expect candidates/duration in stats * Update test_gc from v3.14.3 * Update test_gc.py from CPython v3.15.0a5 Taken from v3.15 (not v3.14.3) because get_stats() candidates/duration fields were added in 3.13+ and the corresponding test assertions only exist in 3.15. * Fix gc_state build on wasm32: skip Instant timing * Add candidates/duration to gc callback info, mark v3.15 test failures * Fix gc.get_referrers to exclude executing frames, fix Future cancelled exc leak - get_referrers: skip frame objects on the execution stack, since they are not GC-tracked in CPython (_PyInterpreterFrame) - _asyncio Future/Task make_cancelled_error_impl: clear the stored cancelled exception after returning it, matching the Python _make_cancelled_error behavior * Fix gc.get_threshold to return actual gen2 threshold value * Fix inconsistent GC count reset in early-return paths Use the same reset_end formula in unreachable-empty early returns as in the main collection path and collecting-empty path. * Accept keyword arguments in socket.__init__ Use a FromArgs struct instead of a positional-only tuple so that family, type, proto, and fileno can be passed as keyword arguments. * Disable comp_inlined in symbol table to match compiler The compiler does not yet implement PEP 709 inlined comprehensions (is_inlined_comprehension_context always returns false), but the symbol table was marking comprehensions as inlined. This mismatch could cause comprehension-local symbols to be merged into the parent scope while the compiler still looks them up in a separate scope. --------- Co-authored-by: CPython Developers <>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| types::{Constructor, IterNext, Iterable, SelfIter}, | ||
| }, | ||
| }; | ||
| use ruff_python_ast::PySourceType; |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| use ruff_python_ast::PySourceType; | |
| use core::fmt; | |
| use ruff_python_ast::PySourceType; |
crates/stdlib/src/_tokenize.rs
Outdated
| }; | ||
| use ruff_source_file::{LineIndex, LineRanges}; | ||
| use ruff_text_size::{Ranged, TextSize}; | ||
| use core::fmt; |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| use core::fmt; |
crates/stdlib/src/_tokenize.rs
Outdated
| let parsed = | ||
| parse_unchecked_source(&accumulated, PySourceType::Python); |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| let parsed = | |
| parse_unchecked_source(&accumulated, PySourceType::Python); | |
| let parsed = parse_unchecked_source(&accumulated, PySourceType::Python); |
crates/stdlib/src/_tokenize.rs
Outdated
| let result = | ||
| emit_next_token(&mut state, zelf.extra_tokens, vm)?; |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| let result = | |
| emit_next_token(&mut state, zelf.extra_tokens, vm)?; | |
| let result = emit_next_token(&mut state, zelf.extra_tokens, vm)?; |
crates/stdlib/src/_tokenize.rs
Outdated
| let full_line = | ||
| source.full_line_str(TextSize::from(offset.min(source.len()) as u32)); |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| let full_line = | |
| source.full_line_str(TextSize::from(offset.min(source.len()) as u32)); | |
| let full_line = source.full_line_str(TextSize::from(offset.min(source.len()) as u32)); |
crates/stdlib/src/_tokenize.rs
Outdated
| let last_line_text = source.full_line_str(TextSize::from( | ||
| source.len().saturating_sub(1) as u32, | ||
| )); |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| let last_line_text = source.full_line_str(TextSize::from( | |
| source.len().saturating_sub(1) as u32, | |
| )); | |
| let last_line_text = | |
| source.full_line_str(TextSize::from(source.len().saturating_sub(1) as u32)); |
crates/stdlib/src/_tokenize.rs
Outdated
| }; | ||
|
|
||
| let result = make_token_tuple( | ||
| vm, TOKEN_ENDMARKER, "", em_line, em_col, em_line, em_col, em_line_str, |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| vm, TOKEN_ENDMARKER, "", em_line, em_col, em_line, em_col, em_line_str, | |
| vm, | |
| TOKEN_ENDMARKER, | |
| "", | |
| em_line, | |
| em_col, | |
| em_line, | |
| em_col, | |
| em_line_str, |
crates/stdlib/src/_tokenize.rs
Outdated
| let exc = vm.new_exception_msg( | ||
| vm.ctx.exceptions.syntax_error.to_owned(), | ||
| msg.into(), | ||
| ); |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| let exc = vm.new_exception_msg( | |
| vm.ctx.exceptions.syntax_error.to_owned(), | |
| msg.into(), | |
| ); | |
| let exc = vm.new_exception_msg(vm.ctx.exceptions.syntax_error.to_owned(), msg.into()); |
crates/stdlib/src/_tokenize.rs
Outdated
| TokenKind::IpyEscapeCommand | ||
| | TokenKind::Question | ||
| | TokenKind::Unknown => 67, // ERRORTOKEN |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| TokenKind::IpyEscapeCommand | |
| | TokenKind::Question | |
| | TokenKind::Unknown => 67, // ERRORTOKEN | |
| TokenKind::IpyEscapeCommand | TokenKind::Question | TokenKind::Unknown => 67, // ERRORTOKEN |
crates/stdlib/src/lib.rs
Outdated
| #[path = "_tokenize.rs"] | ||
| mod _tokenize; |
There was a problem hiding this comment.
[auto-format] reported by reviewdog 🐶
| #[path = "_tokenize.rs"] | |
| mod _tokenize; |
* Align methods for newtype opargs
Bump 3.14.3 modulefinder
Update generator related tests from 3.14.3
* Add strict parameter to map() builtin * Refactor map IterNext to match zip style
Add git diff --exit-code step to fail the check when formatters produce changes. Previously reviewdog only posted suggestions without failing the workflow.
…e on the Android platform. (RustPython#7402)
Fix pr-format CI to fail on formatting changes
Bumps the openssl group with 2 updates: [openssl](https://github.com/rust-openssl/rust-openssl) and [openssl-sys](https://github.com/rust-openssl/rust-openssl). Updates `openssl` from 0.10.75 to 0.10.76 - [Release notes](https://github.com/rust-openssl/rust-openssl/releases) - [Commits](rust-openssl/rust-openssl@openssl-v0.10.75...openssl-v0.10.76) Updates `openssl-sys` from 0.9.111 to 0.9.112 - [Release notes](https://github.com/rust-openssl/rust-openssl/releases) - [Commits](rust-openssl/rust-openssl@openssl-sys-v0.9.111...openssl-sys-v0.9.112) --- updated-dependencies: - dependency-name: openssl dependency-version: 0.10.76 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: openssl - dependency-name: openssl-sys dependency-version: 0.9.112 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: openssl ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [quote](https://github.com/dtolnay/quote) from 1.0.44 to 1.0.45. - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](dtolnay/quote@1.0.44...1.0.45) --- updated-dependencies: - dependency-name: quote dependency-version: 1.0.45 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [memmap2](https://github.com/RazrFalcon/memmap2-rs) from 0.9.9 to 0.9.10. - [Changelog](https://github.com/RazrFalcon/memmap2-rs/blob/master/CHANGELOG.md) - [Commits](RazrFalcon/memmap2-rs@v0.9.9...v0.9.10) --- updated-dependencies: - dependency-name: memmap2 dependency-version: 0.9.10 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
During STARTTLS handshake, sock_recv(16KB) could consume application data that arrived alongside handshake records. The consumed data ended up in rustls's internal buffer where select() could not detect it, causing asyncore-based servers to miss readable events and the peer to time out. Use MSG_PEEK to find the TLS record boundary, then recv() only one complete record. Remaining data stays in the kernel TCP buffer, visible to select(). This matches OpenSSL's default no-read-ahead behaviour. Fixes flaky test_poplib (TestPOP3_TLSClass) failures.
No description provided.