Skip to content

Commit f6f8346

Browse files
committed
Wait for the worker threads when the GC cleared the dict first
tp_clear clears self->dict before tp_dealloc runs when the compressor is freed by the garbage collector, so testing it skipped the wait. Add a test case that frees the busy compressor through a cycle.
1 parent 43e7b7e commit f6f8346

2 files changed

Lines changed: 11 additions & 4 deletions

File tree

‎Lib/test/test_zstd.py‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def test_free_busy_multithread_compressor_with_dict(self):
379379
# Whether a failure is detected depends on the memory allocator,
380380
# so use a fresh process for each case.
381381
code = textwrap.dedent("""
382-
import random, sys
382+
import gc, random, sys
383383
from compression.zstd import (CompressionParameter,
384384
ZstdCompressor, ZstdDict)
385385
@@ -401,11 +401,18 @@ def test_free_busy_multithread_compressor_with_dict(self):
401401
pass
402402
finally:
403403
_testcapi.remove_mem_hooks()
404-
if sys.argv[1] != 'exit':
404+
if sys.argv[1] == 'gc':
405+
# The garbage collector clears the compressor before
406+
# deallocating it.
407+
cycle = [c]
408+
cycle.append(cycle)
409+
del c, cycle
410+
gc.collect()
411+
elif sys.argv[1] != 'exit':
405412
del c
406413
# Otherwise the compressor is freed at interpreter exit.
407414
""")
408-
cases = ['del', 'exit']
415+
cases = ['del', 'gc', 'exit']
409416
try:
410417
import _testcapi # noqa: F401
411418
except ImportError:

‎Modules/_zstd/compressor.c‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ ZstdCompressor_dealloc(PyObject *ob)
432432

433433
/* Free compression context */
434434
if (self->cctx) {
435-
if (self->mt_maybe_busy && self->dict != NULL) {
435+
if (self->mt_maybe_busy) {
436436
/* ZSTD_freeCCtx() (as of libzstd 1.5.7) frees the context's own
437437
copy of a dictionary loaded with ZSTD_CCtx_loadDictionary()
438438
before it stops the worker threads, which may still be

0 commit comments

Comments
 (0)