Skip to content

Serialize bytearray exports with resizing - #9087

Merged
youknowone merged 5 commits into
RustPython:mainfrom
youknowdot:fix-bytearray-buffer-race
Oct 12, 2026
Merged

youknowone merged 5 commits into
RustPython:mainfrom
youknowdot:fix-bytearray-buffer-race

Conversation

@youknowdot

@youknowdot youknowdot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fix a main-common bytearray buffer race surfaced by #8951 macOS CI: decoding used a buffer descriptor of 4 MiB after the underlying bytearray had been cleared.

  • Keep the bytearray read lock through descriptor creation and export retention; preserve early export rejection and recheck exports after acquiring the resize lock.
  • Route initializer replacement and sequence-slot deletion through the resize guard. Clear before initializer conversion, while preserving the successful zero-index callback's no-write behavior without calling __index__ twice.
  • Make RawIOBase.read validate the count, perform a guarded resize, and take the temporary buffer, following pinned CPython 3.15.0 source and preserving retained-view errors.
  • Add bounded Python export-lifetime and concurrent decode/memoryview regressions. No Lib/ files or existing assertions are changed.

Base: f39da82d9d38cd5bdceb9e645205e830f65126fb.
Head: d0819a2fabf2017c5603e089acc7c3a22020f241.

Validation

  • Independent source review of lock ordering, callback/reentry boundaries, retain/release ownership, and each changed mutation path.
  • Native default-feature debug build and cargo check passed; root and matching-feature VM-library Clippy passed with -D warnings; normal commit hooks passed.
  • Both new snippets and existing builtin_bytearray.py / builtin_bytes.py passed on the exact stamped candidate, each in a timeout-controlled subprocess.
  • The unchanged current-main test_bytes.FreeThreadingTest.test_free_threading_bytearray passed once in an isolated subprocess. Its body predates final CPython's additional take_bytes cases; this is validation of the failing CI method, not full final-bytearray API coverage.
  • Both new snippets passed on certified CPython 3.15.0 (d220409a13b77de7a6c30abe16ea90db01528edc). Constructor and raw-I/O error/order semantics were checked against that source.
  • A qualified pre-fix Implement PEP 814 frozendict #8951 native binary with source-identical affected runtime files fails the new exported-initializer regression. Local contention and canonical race runs passed on the baseline too; the actual race-before evidence is the hosted macOS panic and source interleavings, not a claimed deterministic local reproduction.
  • Candidate executable stamp, own embedded standard-library path, imported module origins, and artifact hashes were verified.

Full workspace/C-API suites, release validation and non-Linux runtime coverage were not run locally. Existing incremental-iterable constructor differences, the public Rust mutable-vector API boundary and final take_bytes API additions remain outside this repair. The sequence-slot deletion change has source review rather than direct C-API runtime coverage. Keep this PR draft and unmerged pending hosted CI and maintainer review.

AI assistance

OpenAI Codex implemented, reviewed and validated this change under maintainer direction. The exact model identifier is unavailable in this environment; the commit includes an Assisted-by trailer. This draft does not claim completed human validation.

Summary by CodeRabbit

  • Bug Fixes
    • Improved bytearray behavior when buffers are actively exported or modified during operations, including searching, comparisons, translation, padding, initialization, and deletion.
    • Improved handling of temporary buffers during reads, including resizing and allocation failures.
  • Tests
    • Added coverage for bytearray exports, callbacks, and concurrent resizing.

Keep descriptor acquisition and export retention under the bytearray read lock, and recheck exports after acquiring a resize lock. Guard initializer and sequence deletion writes, preserve zero-index initialization callbacks, and match RawIOBase.read buffer ownership without bypassing export checks.

Add bounded Python export-lifetime and concurrent decode/memoryview regression coverage.

Assisted-by: OpenAI Codex:model identifier unavailable
@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: RustPython/RustPython/.coderabbit.yml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c2502a4d-d8b4-4f5f-b077-60c788bbf789

📥 Commits

Reviewing files that changed from the base of the PR and between a0fec1f and f163e13.


📒 Files selected for processing (1)
  • extra_tests/snippets/builtin_bytearray.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.



📝 Walkthrough

Walkthrough

Bytearray operations now use buffer exports and snapshots around callback-capable inputs. Initialization, deletion, and resizing account for active exports. Concatenation acquires operand buffers, and RawIOBase.read resizes and transfers its result buffer.

Changes

Bytearray and buffer handling

Layer / File(s) Summary
Handle buffers during bytearray operations
crates/vm/src/anystr.rs, crates/vm/src/bytes_inner.rs, crates/vm/src/builtins/bytearray.rs, extra_tests/snippets/builtin_bytearray.py
Search, affix checks, translation, comparison, and padding use buffer exports, snapshots, and shared byte-operation helpers. Tests exercise callback order, mutation attempts, and buffer acquisition failures.
Guard initialization, deletion, and buffer resizing
crates/vm/src/builtins/bytearray.rs, crates/vm/src/bytes_inner.rs, crates/vm/src/stdlib/_io.rs, extra_tests/snippets/builtin_bytearray.py
Initialization clears existing contents before conversion and rechecks resize eligibility. Integer deletion validates indices before export rejection. Buffer length reads and RawIOBase.read use guarded buffer operations. Tests cover active exports, read results, and concurrent resizing.
Acquire operand buffers for concatenation
crates/vm/src/builtins/bytearray.rs, extra_tests/snippets/builtin_bytearray.py
Concatenation acquires buffers from both operands, checks length and allocation errors, and builds a new bytearray. Tests check callback behavior, release order, and acquisition failures.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant ByteArrayFind
  participant TargetByteArray
  participant NeedleBuffer
  ByteArrayFind->>TargetByteArray: acquire export
  ByteArrayFind->>NeedleBuffer: acquire buffer
  NeedleBuffer-->>ByteArrayFind: return needle bytes
  ByteArrayFind->>TargetByteArray: search within adjusted range
  ByteArrayFind->>NeedleBuffer: release buffer
  ByteArrayFind->>TargetByteArray: release export
Loading

Merge Risk: ⚪ Minimal · up to f163e

The supplied changes add regression tests for bytearray export and resize handling. No concrete merge-blocking issue was found in the supplied test changes; hosted CI and maintainer review remain pending as the PR states.

Pre-merge checks | Passed 2 | Failed 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Linked Issues check Warning Open directly linked issue [#8951] requires PEP 814 frozendict, including immutable mappings, frozen globals and namespaces, applicable dictionary C-API reads, and focused regression tests. The curr… Implement the applicable [#8951] frozendict requirements in this PR, or remove the direct link to [#8951] and link this bytearray fix to the correct issue.
Out of Scope Changes check Warning The current implementation and tests cover bytearray export lifetime, resize synchronization, buffer handling, raw I/O, and concurrent bytearray behavior. These changes support the reported bytearray … Move the bytearray implementation and regression tests to a PR linked to the bytearray race issue, or provide a directly linked coding requirement that connects these changes to [#8951].
Docstring Coverage Warning Docstring coverage is 12.32% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 138 functions across 10 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: coordinating bytearray exports with resizing to address buffer races.

Full details: Linked Issues check

Explanation

Open directly linked issue [#8951] requires PEP 814 frozendict, including immutable mappings, frozen globals and namespaces, applicable dictionary C-API reads, and focused regression tests. The current PR changes PyByteArray, bytearray helpers, _io.RawIOBase.read, and builtin_bytearray.py. The current PR contains no demonstrated frozendict implementation or tests.


Full details: Out of Scope Changes check

Explanation

The current implementation and tests cover bytearray export lifetime, resize synchronization, buffer handling, raw I/O, and concurrent bytearray behavior. These changes support the reported bytearray race, but they do not implement or test the directly linked issue's frozendict requirements. The inspected current test file is extra_tests/snippets/builtin_bytearray.py.


  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codspeed

codspeed Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

✅ 62 untouched benchmarks
⏩ 4 skipped benchmarks1


Comparing youknowdot:fix-bytearray-buffer-race (f163e13) with main (9ea138c)

Open in CodSpeed

Footnotes

  1. 4 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@youknowone
youknowone marked this pull request as ready for review October 12, 2026 01:14
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T05:36:42.607295Z f163e13 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔇 Additional comments (8)
crates/vm/src/bytes_inner.rs (1)

228-245: LGTM!

Also applies to: 281-282

crates/vm/src/builtins/bytearray.rs (4)

779-790: LGTM!


848-852: LGTM!


921-921: LGTM!


864-869: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

⚠️ Unverified finding
Verification ran but could not confirm this finding. It is shown for review, not as a verified issue.

The export check after the lock does not stop a new export from being acquired while the guard is held.

try_resizable_opt checks exports after it takes the write lock. Another thread can still increment exports without the lock while this thread holds the guard. These paths do this:

  • count
  • find_exported
  • join
  • split
  • __contains__
  • hex

For example, __contains__ increments the counter and then calls self.inner(). That call waits on the read lock until the resize completes, so memory safety holds for these paths.

as_buffer takes the read lock before PyBuffer::new retains the export, so buffer exports are also safe. The design is correct only if every path that increments exports takes the read lock before it reads the data. Add a short comment that states this rule so future export paths follow it.

extra_tests/snippets/builtin_bytearray_exports.py (1)

1-136: LGTM!

extra_tests/snippets/builtin_bytearray_threading.py (1)

1-55: LGTM!

crates/vm/src/stdlib/_io.rs (1)

765-771: LGTM!


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: RustPython/RustPython/.coderabbit.yml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a3dd5f43-6526-46e8-9c38-582c3e3e72a7
📥 Commits

Reviewing files that changed from the base of the PR and between f39da82 and d0819a2.

📒 Files selected for processing (5)
  • crates/vm/src/builtins/bytearray.rs
  • crates/vm/src/bytes_inner.rs
  • crates/vm/src/stdlib/_io.rs
  • extra_tests/snippets/builtin_bytearray_exports.py
  • extra_tests/snippets/builtin_bytearray_threading.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d0819a2fab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/vm/src/builtins/bytearray.rs Outdated
let mut inner = options.get_inner(bytearray_from_object, vm)?;
core::mem::swap(&mut *zelf.inner_mut(), &mut inner);
// Reject exports and clear existing contents before converting source.
zelf.try_resizable(vm)?.elements.clear();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Allow no-op initialization of exported empty bytearrays

When an empty bytearray already has a live memoryview, __init__() and __init__(0) perform no resize; CPython permits both and still invokes conversion callbacks for an int-like zero. The unconditional resize guard here instead raises BufferError before options conversion, regressing the previously successful no-op and suppressing those callbacks. Skip the initial guard/clear when the current length is zero and only reject if the eventual result actually needs a resize.

AGENTS.md reference: AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

Comment on lines +787 to +788
if zero_count {
return Ok(());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Release the previous allocation for zero-count initialization

When a large existing bytearray is reinitialized with an integer (or int-like value) of zero, this early return follows Vec::clear(), which preserves capacity, so bytearray.__alloc__() continues to expose the old allocation and potentially gigabytes remain held for the object's lifetime. The old implementation swapped in the newly created empty inner and released that storage; replace the backing vector while performing the initial clear so the zero-count callback behavior is kept without retaining the old allocation.

Useful? React with 👍 / 👎.

Comment thread crates/vm/src/builtins/bytearray.rs Outdated
zelf._setitem_by_index(i, &value, vm)
} else {
zelf.borrow_buf_mut().delitem_by_index(vm, i)
zelf.try_resizable(vm)?.elements.delitem_by_index(vm, i)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the sequence index before rejecting an export

When a C extension calls PySequence_DelItem on a bytearray with a live export and a positive index at or beyond the current length, this guard runs before delitem_by_index can validate the bounds, so the call now raises BufferError; CPython's bytearray sequence slot reports IndexError for such an index without attempting a resize. Validate the index before acquiring the resize guard, then revalidate under the guard, so only a valid deletion is treated as a resize.

AGENTS.md reference: AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

Reset initializer storage before zero-count callbacks and returns. Validate integer deletion indices with a nonblocking snapshot before export rejection where possible, then revalidate under the resize guard. Preserve fast export rejection when contended to avoid codec callback deadlocks.

Add Python regressions for exported-empty rejection, initializer capacity release, callback ordering, and ordinary deletion error precedence.

Assisted-by: OpenAI Codex:model identifier unavailable

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcd4f4c8ae

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

let mut inner = options.get_inner(bytearray_from_object, vm)?;
core::mem::swap(&mut *zelf.inner_mut(), &mut inner);
// Reject exports and clear existing contents before converting source.
zelf.try_resizable(vm)?.elements = Vec::new();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject reentrant initialization without self-deadlocking

When target + other reaches a Python other.__buffer__ that calls target.__init__(object()) (and catches the exception), AsSequence::concat is still holding target.inner() for reading. This new eager try_resizable then waits for the same thread's write lock, so the expression hangs; in the parent, invalid-source conversion raised TypeError before any write lock was taken and concatenation completed. Mark the outer borrow as an export so reentry gets BufferError, or otherwise avoid taking this write lock reentrantly.

Useful? React with 👍 / 👎.


from testutils import assert_raises

for args in ((), (b"abc",), (b"x",), (b"",), (object(),)):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the prohibited test-logic additions

Remove this new regression snippet and the two sibling builtin_bytearray_* snippets: the repository's critical test policy allows test-file edits only for adding or removing expected-failure markers, whereas these files introduce new assertions, control flow, and test data. Keeping them in this change violates the contribution rules even if the tests pass.

AGENTS.md reference: AGENTS.md:L273-L279

Useful? React with 👍 / 👎.

Acquire both operand exports before borrowing their bytes and release them in CPython order. Cover reentrant initialization, mutable callbacks and export cleanup through public concatenation APIs.

Assisted-by: OpenAI Codex:model identifier unavailable

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9fdae0a3f7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

let mut inner = options.get_inner(bytearray_from_object, vm)?;
core::mem::swap(&mut *zelf.inner_mut(), &mut inner);
// Reject exports and clear existing contents before converting source.
zelf.try_resizable(vm)?.elements = Vec::new();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject initializer reentry instead of waiting on the read lock

The new concat buffering removes the earlier target + other deadlock, but target == other still calls zelf.inner().cmp(...) with a read guard while other.__buffer__ runs. If that callback calls target.__init__(object()) and catches the exception, this eager try_resizable waits forever for the same thread's read guard; the parent converted the invalid source first and returned TypeError instead. Mark outer callback borrows such as comparison and starts/endswith as exports, or make this guard fail rather than wait reentrantly.

Useful? React with 👍 / 👎.


from testutils import assert_raises

for concat in (operator.add, operator.concat, bytearray.__add__):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the newly added concat test snippet

This fourth regression file is fresh evidence beyond the three snippets named in the existing review: it adds a loop, helper classes, and assertions even though the scoped critical policy permits test-file edits only to add or remove expected-failure decorators. Remove this test logic rather than expanding the prohibited test changes.

AGENTS.md reference: AGENTS.md:L273-L279

Useful? React with 👍 / 👎.

Keep operation-specific export and release ordering for comparisons, searches, affix tuples and translation. Resolve padding arguments before borrowing the receiver, and retain buffer owners through computation without holding bytearray locks across Python callbacks.

Add bounded Python regressions for callback mutation, reentrant initialization, lazy affixes, subclass protocols and ordered cleanup.

Assisted-by: OpenAI Codex:model identifier unavailable

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a0fec1f8c0

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +970 to +971
let left = Self::buffer_snapshot(left, vm)?;
let right = Self::buffer_snapshot(right, vm)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid cloning both buffers during comparisons

When equal-length operands are large, and for every ordering comparison, these snapshots allocate and copy both complete operands before comparing them; even a == a for an exact bytearray now requires two full-size temporary allocations. The parent implementation compared borrowed slices without this extra 2× memory requirement, so otherwise valid comparisons can now raise MemoryError or cause severe allocation latency; keep the exports alive but compare lock-safe borrowed views, or retain the identity fast path for exact bytearrays.

AGENTS.md reference: AGENTS.md:L7-L7

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not make multiple tset files. move 5 files into builtin_bytearray.py

Preserve all existing regression bodies and coverage while following the requested snippet organization.

Assisted-by: OpenAI Codex:model identifier unavailable

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f163e13710

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

assert empty == bytearray()


def test_bytearray_exports():

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the appended test logic

Fresh evidence beyond the earlier separate-snippet comments is that this squashed commit now appends the four regression bodies to builtin_bytearray.py, adding 591 lines of assertions, control flow, and test data. Consolidating them into an existing snippet does not resolve the critical policy violation, because test-file edits are limited to adding or removing expected-failure markers; remove this new test logic or obtain an explicit policy exception.

AGENTS.md reference: AGENTS.md:L273-L279

Useful? React with 👍 / 👎.

Comment on lines +1100 to +1101
left.append_to(&mut bytes);
right.append_to(&mut bytes);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Snapshot aliased concat operands atomically

When both operands expose the same mutable bytearray (for example a + a) and another thread performs a same-length assignment, these two append_to calls acquire and release the bytearray read lock independently. Exports block resizing but not same-size writes, so the writer can run between the calls and produce an old left half plus a new right half, a result that no atomic execution of a + a can produce; reuse one snapshot when the root exporters alias, or otherwise keep the shared storage stable across both copies.

Useful? React with 👍 / 👎.

Comment on lines +935 to +938
if zero_count {
return Ok(());
}
core::mem::swap(&mut *zelf.try_resizable(vm)?, &mut inner);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat source-less initialization as complete after clearing

When bytearray.__init__() is called without a source and another thread acquires a memoryview after the initial clear, get_inner_with_zero_count leaves this flag false, so the second resize guard raises BufferError. The call has already discarded the old contents and has no remaining write to perform, making a completed clear appear to fail; mark the missing-source case as no-further-write or keep the initial guard through that callback-free path.

Useful? React with 👍 / 👎.

@youknowone
youknowone merged commit 597a422 into RustPython:main Oct 12, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants