-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
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
gc_decref: Assertion "gc_get_refs(g) > 0" failed #99578
Comments
How did you configure Python? (the |
Please run the test with:
|
|
./configure --with-pydebug |
@vstinner may be related: |
Can you please try to bisect the issue?
Then run the sub-set of tests:
Until you reproduce the bug, continue modifying tests.txt. You can keep copies of this file, like tests.txt, tests2.txt, etc. Each time, you remove a bunch of tests. You might also try to run tests in parallel, it spawns one fresh process per test file:
|
Oh, I can reproduce the crash just with:
|
yeah, but I'm making notes on what you suggested, for next time. ;) |
You didn't create the issue so a newbie would have a chance. How's that for a good reason? ;) |
Regression introduced in 2019 by commit 2582d46:
I used test_bug.py, test_bug2.py and a patch to bisect the issue with
test_bug.py: import unittest
from test import support
class SubinterpreterTest(unittest.TestCase):
def test_module_state_shared_in_global(self):
ret = support.run_in_subinterp("pass")
self.assertEqual(ret, 0) test_bug2.py: import unittest
import _imp
from test import support
class SubinterpreterTest(unittest.TestCase):
def test_issue98354(self):
# _imp.create_builtin should raise TypeError
# if 'name' attribute of 'spec' argument is not a 'str' instance
create_builtin = support.get_attribute(_imp, "create_builtin")
class FakeSpec:
def __init__(self, name):
self.name = self
spec = FakeSpec("time")
with self.assertRaises(TypeError):
create_builtin(spec)
class FakeSpec2:
name = [1, 2, 3, 4]
spec = FakeSpec2()
with self.assertRaises(TypeError):
create_builtin(spec)
import builtins
class UnicodeSubclass(str):
pass
class GoodSpec:
name = UnicodeSubclass("builtins")
spec = GoodSpec()
bltin = create_builtin(spec)
self.assertEqual(bltin, builtins)
class UnicodeSubclassFakeSpec(str):
def __init__(self, name):
self.name = self
spec = UnicodeSubclassFakeSpec("builtins")
bltin = create_builtin(spec)
self.assertEqual(bltin, builtins) patch: diff --git a/Python/import.c b/Python/import.c
index 505688400e..8f6599cad4 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -1263,6 +1263,14 @@ _imp_create_builtin(PyObject *module, PyObject *spec)
return NULL;
}
+ if (!PyUnicode_Check(name)) {
+ PyErr_Format(PyExc_TypeError,
+ "name must be string, not %.200s",
+ Py_TYPE(name)->tp_name);
+ Py_DECREF(name);
+ return NULL;
+ }
+
mod = _PyImport_FindExtensionObject(name, name);
if (mod || _PyErr_Occurred(tstate)) {
Py_DECREF(name); I wrote different flavors of the patch depending on the Python version. |
I love |
On 11/19/22 10:47, Victor Stinner wrote:
I love |git bisect|. It prevented me to have to manually go through 9422 commits: November 20, 2019 to November 19, 2022, over 3 years of commits!
Dude, I'm going to have to study the other email you sent, that's awesome!
Leam
…--
Automation Engineer (reuel.net/resume)
Scribe: The Domici War (domiciwar.net)
General Ne'er-do-well (github.com/LeamHall)
|
Simpler reproducer: # CRASH: https://github.com/python/cpython/issues/99578
import _imp
import _testcapi
import builtins
import gc
ret = _testcapi.run_in_subinterp("pass")
if ret != 0:
raise Exception(1)
gc.collect()
class Spec:
name = "builtins"
spec = Spec()
mod = _imp.create_builtin(spec)
if mod is not builtins:
raise Exception(2)
print("GC collect")
gc.collect() # <===== CRASH OCCURS HERE
mod = None
print("exit") |
Why not using Py_DECREF()? |
If |
I wrote PR #99642 which adds a test to reproduce the crash, and a fix for the crash. History of this issue:
This bug was well hidden since running test_imp alone was not enough: a previous test must create a sub-intepreter (ex: test_capi). To get the bug, you need multiple conditions:
In fact, this crash is not a regression.
But this reference bug cannot be seen before my change in 2019: commit 2582d46. |
Fix a reference bug in _imp.create_builtin() after the creation of the first sub-interpreter for modules "builtins" and "sys".
Fix a reference bug in _imp.create_builtin() after the creation of the first sub-interpreter for modules "builtins" and "sys". (cherry picked from commit cb2ef8b) Co-authored-by: Victor Stinner <vstinner@python.org>
Fix a reference bug in _imp.create_builtin() after the creation of the first sub-interpreter for modules "builtins" and "sys". (cherry picked from commit cb2ef8b) Co-authored-by: Victor Stinner <vstinner@python.org>
I can reproduce the crash on Python 3.11 without the fix using:
|
At least, on main, I confirm that
Using -j0, it just takes 7 min 12 sec using "14 child processes" (my laptop CPU has 12 threads) ;-) |
On 11/21/22 07:54, Victor Stinner wrote:
The crash was fixed in 3.10, 3.11 and main branches. Fix in main: cb2ef8b <cb2ef8b>
Thanks for the bug report @LeamHall <https://github.com/LeamHall>. Please check that |./python -m test| no long crash for you. But then, I suggest to adding |-j0| to run tests in parallel.
Running tests (up to 317 of 433), mine take a while. The test_imp did pass though, so I think your work fixed things.
Leam
…--
Automation Engineer (reuel.net/resume)
Scribe: The Domici War (domiciwar.net)
General Ne'er-do-well (github.com/LeamHall)
|
Thanks for the great detective work, @vstinner! |
Bug report
Error whlie testing the main branch. May be similar to:
The problem
When running
./python -m test
:Your environment
Message log
Linked PRs
The text was updated successfully, but these errors were encountered: