Make py_zstd_compress_mt2 thread-safe#321
Open
KowalskiThomas wants to merge 1 commit into
Open
Conversation
645526c to
693cd72
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What is this PR?
This PR is a fix for a crash we witnessed in a service of ours.
py_zstd_compress_mt2used a single global compression context (at the module level),m_cctx, which is thus shared across all calls:python-zstd/src/python-zstd.h
Line 130 in fec54dd
python-zstd/src/python-zstd.c
Lines 279 to 281 in fec54dd
Since
ZSTD_CCtxis not thread-safe, and because compression releases the GIL, two Python threads calling these functions at the same time use the same context concurrently. This can corrupt the state and lead to out-of-bounds access inside zstd.The crash was detected in this form:
Looking further into it, we found another race as well. When called with different
levelvalues,reset_cContextfrees and recreatesm_cctx. If one thread does this while another is still inside the GIL-releasedZSTD_compress2, the latter compresses into a freed context.Proposed fix
The fix proposed in this PR is to make
py_zstd_compress_mt2create and free its ownZSTD_CCtxon each call, instead of sharing the module-global one. This is the same pattern already used bypy_zstd_compress_mt:python-zstd/src/python-zstd.c
Lines 141 to 149 in fec54dd