Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Builder: Re-use the old buffer after trimming #581

Merged
merged 2 commits into from
May 20, 2023

Conversation

clyring
Copy link
Member

@clyring clyring commented Apr 10, 2023

It might be nice to work out how much this affects the balance of power between trimming and not trimming. But it's a nice incremental improvement without that.

@Bodigrim
Copy link
Contributor

@clyring could you please rebase to get a clean CI run?

@Bodigrim Bodigrim added this to the 0.11.5.0 milestone May 20, 2023
@Bodigrim Bodigrim merged commit 5c4d236 into haskell:master May 20, 2023
@Bodigrim
Copy link
Contributor

Thanks!

Bodigrim pushed a commit to Bodigrim/bytestring that referenced this pull request May 28, 2023
adamgundry added a commit to adamgundry/bytestring that referenced this pull request Aug 8, 2024
`toLazyByteString :: Builder -> LazyByteString` had a race condition that could
generate wrong results if two threads concurrently evaluated the result.  This
bug was introduced in haskell#581 (5c4d236) and first
present in release 0.11.5.0 (as 0c030bb).

Due to the use of `unsafeDupablePerformIO` for performance, it is critical that
any IO actions executed when running a `Builder` can be interrupted or executed
multiple times.  In principle, filling a buffer is safe provided the buffer is
used only once and the same bytes are written each time. However, `wrapChunk` in
`buildStepToCIOS` would re-use a buffer in the trimming case after copying its
contents to produce a new trimmed chunk. This is safe when run in a single
thread, but if two threads simultaneously execute the code, one of them may
still be copying the contents while the other starts overwriting the buffer.

This patch fixes `wrapChunk` to unconditionally allocate a new buffer after
trimming, rather than re-using the old buffer. This will presumably come at a
slight performance cost for builders inserting many trimmed chunks.
clyring pushed a commit that referenced this pull request Sep 18, 2024
`toLazyByteString :: Builder -> LazyByteString` had a race condition that could
generate wrong results if two threads concurrently evaluated the result.  This
bug was introduced in #581 (5c4d236) and first
present in release 0.11.5.0 (as 0c030bb).

Due to the use of `unsafeDupablePerformIO` for performance, it is critical that
any IO actions executed when running a `Builder` can be interrupted or executed
multiple times.  In principle, filling a buffer is safe provided the buffer is
used only once and the same bytes are written each time. However, `wrapChunk` in
`buildStepToCIOS` would re-use a buffer in the trimming case after copying its
contents to produce a new trimmed chunk. This is safe when run in a single
thread, but if two threads simultaneously execute the code, one of them may
still be copying the contents while the other starts overwriting the buffer.

This patch fixes `wrapChunk` to unconditionally allocate a new buffer after
trimming, rather than re-using the old buffer. This will presumably come at a
slight performance cost for builders inserting many trimmed chunks.
Bodigrim pushed a commit that referenced this pull request Oct 9, 2024
`toLazyByteString :: Builder -> LazyByteString` had a race condition that could
generate wrong results if two threads concurrently evaluated the result.  This
bug was introduced in #581 (5c4d236) and first
present in release 0.11.5.0 (as 0c030bb).

Due to the use of `unsafeDupablePerformIO` for performance, it is critical that
any IO actions executed when running a `Builder` can be interrupted or executed
multiple times.  In principle, filling a buffer is safe provided the buffer is
used only once and the same bytes are written each time. However, `wrapChunk` in
`buildStepToCIOS` would re-use a buffer in the trimming case after copying its
contents to produce a new trimmed chunk. This is safe when run in a single
thread, but if two threads simultaneously execute the code, one of them may
still be copying the contents while the other starts overwriting the buffer.

This patch fixes `wrapChunk` to unconditionally allocate a new buffer after
trimming, rather than re-using the old buffer. This will presumably come at a
slight performance cost for builders inserting many trimmed chunks.
Bodigrim pushed a commit that referenced this pull request Oct 15, 2024
`toLazyByteString :: Builder -> LazyByteString` had a race condition that could
generate wrong results if two threads concurrently evaluated the result.  This
bug was introduced in #581 (5c4d236) and first
present in release 0.11.5.0 (as 0c030bb).

Due to the use of `unsafeDupablePerformIO` for performance, it is critical that
any IO actions executed when running a `Builder` can be interrupted or executed
multiple times.  In principle, filling a buffer is safe provided the buffer is
used only once and the same bytes are written each time. However, `wrapChunk` in
`buildStepToCIOS` would re-use a buffer in the trimming case after copying its
contents to produce a new trimmed chunk. This is safe when run in a single
thread, but if two threads simultaneously execute the code, one of them may
still be copying the contents while the other starts overwriting the buffer.

This patch fixes `wrapChunk` to unconditionally allocate a new buffer after
trimming, rather than re-using the old buffer. This will presumably come at a
slight performance cost for builders inserting many trimmed chunks.
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