75 Commits

Author SHA1 Message Date
Tim Peters
64173c8793 handle_weakrefs(): Simplification -- there's no need to make a second
pass over the unreachable weakrefs-with-callbacks to unreachable objects.
2004-10-31 22:27:45 +00:00
Tim Peters
7d37a2a564 SF 1055820: weakref callback vs gc vs threads
In cyclic gc, clear all weakrefs to unreachable objects before allowing any
Python code (weakref callbacks or __del__ methods) to run.

This is a critical bugfix, affecting all versions of Python since weakrefs
were introduced.
2004-10-31 00:13:07 +00:00
Guido van Rossum
5c20156349 Silence GCC warning when asserts are turned off. 2003-11-24 04:02:31 +00:00
Tim Peters
ca6919c180 SF bug 839548: Bug in type's GC handling causes segfaults.
Also SF patch 843455.

This is a critical bugfix, backported from 2.4 development.
I don't intend to backport beyond 2.3 maint.  The bugs this fixes
have been there since weakrefs were introduced.
2003-11-20 22:13:51 +00:00
Guido van Rossum
e13ddc9ec8 - New C API PyGC_Collect(), same as calling gc.collect().
- Call this in Py_Finalize().
- Expand the Misc/NEWS text on PY_LONG_LONG.
2003-04-17 17:29:22 +00:00
Tim Peters
730f5535ba s/referrents/referents/g. Gotta love that referrers remains rife with rs. 2003-04-08 17:17:17 +00:00
Tim Peters
0f81ab6d88 Finished implementing gc.get_referrents(): dealt with error and end
cases, wrote docs, added a test.
2003-04-08 16:39:48 +00:00
Tim Peters
fb2ab4d5ae Comment repair; no semantic changes. 2003-04-07 22:41:24 +00:00
Tim Peters
f6b8045ca5 Reworked has_finalizer() to use the new _PyObject_Lookup() instead
of PyObject_HasAttr(); the former promises never to execute
arbitrary Python code.  Undid many of the changes recently made to
worm around the worst consequences of that PyObject_HasAttr() could
execute arbitrary Python code.

Compatibility is hard to discuss, because the dangerous cases are
so perverse, and much of this appears to rely on implementation
accidents.

To start with, using hasattr() to check for __del__ wasn't only
dangerous, in some cases it was wrong:  if an instance of an old-
style class didn't have "__del__" in its instance dict or in any
base class dict, but a getattr hook said __del__ existed, then
hasattr() said "yes, this object has a __del__".  But
instance_dealloc() ignores the possibility of getattr hooks when
looking for a __del__, so while object.__del__ succeeds, no
__del__ method is called when the object is deleted.  gc was
therefore incorrect in believing that the object had a finalizer.

The new method doesn't suffer that problem (like instance_dealloc(),
_PyObject_Lookup() doesn't believe __del__ exists in that case), but
does suffer a somewhat opposite-- and even more obscure --oddity:
if an instance of an old-style class doesn't have "__del__" in its
instance dict, and a base class does have "__del__" in its dict,
and the first base class with a "__del__" associates it with a
descriptor (an object with a __get__ method), *and* if that
descriptor raises an exception when __get__ is called, then
(a) the current method believes the instance does have a __del__,
but (b) hasattr() does not believe the instance has a __del__.

While these disagree, I believe the new method is "more correct":
because the descriptor *will* be called when the object is
destructed, it can execute arbitrary Python code at the time the
object is destructed, and that's really what gc means by "has a
finalizer":  not specifically a __del__ method, but more generally
the possibility of executing arbitrary Python code at object
destruction time.  Code in a descriptor's __get__() executed at
destruction time can be just as problematic as code in a
__del__() executed then.

So I believe the new method is better on all counts.

Bugfix candidate, but it's unclear to me how all this differs in
the 2.2 branch (e.g., new-style and old-style classes already
took different gc paths in 2.3 before this last round of patches,
but don't in the 2.2 branch).
2003-04-07 19:21:15 +00:00
Tim Peters
1155887a74 initgc(): Rewrote to use the PyModule_AddXYZ API; cuts code size. 2003-04-06 23:30:52 +00:00
Tim Peters
259272b7a0 handle_finalizers(): Rewrote to call append_objects() and gc_list_merge()
instead of looping.  Smaller and clearer.  Faster, too, when we're not
appending to gc.garbage:  gc_list_merge() takes constant time, regardless
of the lists' sizes.

append_objects():  Moved up to live with the other list manipulation
utilities.
2003-04-06 19:41:39 +00:00
Tim Peters
50c61d5a6c Switched from METH_VARARGS to METH_NOARGS for the 7 module functions that
take no arguments; cuts generated code size.
2003-04-06 01:50:50 +00:00
Tim Peters
bf384c256e Reworked move_finalizer_reachable() to create two distinct lists:
externally unreachable objects with finalizers, and externally unreachable
objects without finalizers reachable from such objects.  This allows us
to call has_finalizer() at most once per object, and so limit the pain of
nasty getattr hooks.  This fixes the failing "boom 2" example Jeremy
posted (a non-printing variant of which is now part of test_gc), via never
triggering the nasty part of its __getattr__ method.
2003-04-06 00:11:39 +00:00
Tim Peters
f6ae7a43eb move_finalizers(): Rewrote. It's not necessary for this routine
to special-case classic classes, or to worry about refcounts;
has_finalizer() deleted the current object iff the first entry in
the unreachable list has changed.  I don't believe it was correct
to check for ob_refcnt == 1, either:  the dealloc routine would get
called by Py_DECREF then, but there's nothing to stop the dealloc
routine from ressurecting the object, and then gc would remain at
the head of the unreachable list despite that its refcount temporarily
fell to 0 (and that would lead to an infinite loop in move_finalizers()).

I'm still worried about has_finalizer() resurrecting other objects
in the unreachable list:  what's to stop them from getting collected?
2003-04-05 18:40:50 +00:00
Tim Peters
86b993b6cf New comments. Rewrote has_finalizer() as a sequence of ifs instead of
squashed-together conditional operators; makes it much easier to step
thru in the debugger, and to set a breakpoint on the only dangerous
path.
2003-04-05 17:35:54 +00:00
Tim Peters
93ad66dea9 Fixed new seemingly random segfaults, by moving the initialization of
delstr from initgc() into collect().  initgc() isn't called unless the
user explicitly imports gc, so can be used only for initialization of
user-visible module features; delstr needs to be initialized for proper
internal operation, whether or not gc is explicitly imported.

Bugfix candidate?  I don't know whether the new bug was backported to
2.2 already.
2003-04-05 17:15:44 +00:00
Jeremy Hylton
ce136e985a Fix Tim's boom example.
move_finalizers() moves every object from unreachable to collectable
or finalizers, unless the object is deallocated first.
2003-04-04 19:59:06 +00:00
Jeremy Hylton
059b094e29 Add get_referrents() helper function. 2003-04-03 16:29:13 +00:00
Jeremy Hylton
5bd378bfca Add get_referrents() helper function. 2003-04-03 16:28:38 +00:00
Martin v. Löwis
774348c8d6 Fix typo. 2002-11-09 19:54:06 +00:00
Guido van Rossum
4030714a93 For new-style classes, we can now test for tp_del instead of asking
for a __del__ attribute, to see if there's a finalizer.
2002-08-09 17:39:14 +00:00
Tim Peters
803526b9e2 Trashcan cleanup: Now that cyclic gc is always there, the trashcan
mechanism is no longer evil:  it no longer plays dangerous games with
the type pointer or refcounts, and objects in extension modules can play
along too without needing to edit the core first.

Rewrote all the comments to explain this, and (I hope) give clear
guidance to extension authors who do want to play along.  Documented
all the functions.  Added more asserts (it may no longer be evil, but
it's still dangerous <0.9 wink>).  Rearranged the generated code to
make it clearer, and to tolerate either the presence or absence of a
semicolon after the macros.  Rewrote _PyTrash_destroy_chain() to call
tp_dealloc directly; it was doing a Py_DECREF again, and that has all
sorts of obscure distorting effects in non-release builds (Py_DECREF
was already called on the object!).  Removed Christian's little "embedded
change log" comments -- that's what checkin messages are for, and since
it was impossible to correlate the comments with the code that changed,
I found them merely distracting.
2002-07-07 05:13:56 +00:00
Tim Peters
943382c8e5 Removed WITH_CYCLE_GC #ifdef-ery. Holes:
+ I'm not sure what to do about configure.in.  Left it alone.

+ Ditto pyexpat.c.  Fred or Martin will know what to do.
2002-07-07 03:59:34 +00:00
Michael W. Hudson
8b7f131f8b gc_list_move defined but not used. 2002-07-04 17:11:36 +00:00
Tim Peters
aab713bdf7 visit_decref(): Added another assert. 2002-07-02 22:15:28 +00:00