This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: When PyObject_CallMethod fails, refcount is incorrect
Type: resource usage Stage:
Components: Interpreter Core Versions: Python 2.5
process
Status: closed Resolution: works for me
Dependencies: Superseder:
Assigned To: Nosy List: amaury.forgeotdarc, dominic.lavoie
Priority: normal Keywords:

Created on 2008-07-09 16:48 by dominic.lavoie, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue3328.zip dominic.lavoie, 2008-07-09 18:42 Test case archive
Messages (5)
msg69474 - (view) Author: Dominic Lavoie (dominic.lavoie) Date: 2008-07-09 16:48
This issue is similar to issue 1229429. In the called Python method, a 
regular expression fails to compile & PyEval_CallMethod() returns 0. 
However, the reference count is incremented by 1 which prevents the 
object from being destroyed.

Could the problem be in classobject.c, in instancemethod_call() ?

		if (newarg == NULL)
			return NULL;
		Py_INCREF(self);
		PyTuple_SET_ITEM(newarg, 0, self);
		for (i = 0; i < argcount; i++) {
			PyObject *v = PyTuple_GET_ITEM(arg, i);
			Py_XINCREF(v);
			PyTuple_SET_ITEM(newarg, i+1, v);
		}
		arg = newarg;
	}
	result = PyObject_Call((PyObject *)func, arg, kw);
	Py_DECREF(arg);
	return result;
}

If result is null, should Py_DECREF(self) be called in the case where 
self was non-null ?
msg69475 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-07-09 17:06
No, PyTuple_SET_ITEM() "steals" a reference to its argument, so that
ownership is transferred to the tuple.
The reference will be released when the tuple is disposed, with
Py_DECREF(arg).

What makes you think that there is a reference leak? Do you have a test
case?
msg69480 - (view) Author: Dominic Lavoie (dominic.lavoie) Date: 2008-07-09 18:21
My application is fairly complex so I am currently trying to build a simple test case that reproduces the problem. Will let you know as soon as it is ready.

Regards,

Dominic
msg69481 - (view) Author: Dominic Lavoie (dominic.lavoie) Date: 2008-07-09 18:42
OK, I have been able to reproduce the problem with a simple test 
program. All you have to do is compile issue328.c and run it. 
issue328.py compiles an invalid regexp. You will see that the refcount 
goes from 1 to 2 if the regexp compilation fails but stays constant if 
the regexp compilation is successful.
msg69490 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2008-07-09 22:02
Thanks for the short case. It makes everything simpler.
First, note that you get the same behaviour with python-only code:

import re, sys
class Issue3328:
    def f(self):
        # unbalanced parenthesis
        x = re.compile('(123')

o = Issue3328()
sys.getrefcount(o)      # prints 2
o.f()
sys.getrefcount(o)      # prints 3

And this is normal: the last exception contains the traceback (stored in
sys.last_traceback) which contains the live context frames which
reference the "self" variable which is the additional reference to our
object.
Try to provoke another error (any SyntaxError will do) and see the
refcount decrease.

Now, the three variables sys.last_traceback, sys.last_type and
sys.last_value contain the info about the last *uncaught* exception.
An exception is said to be *uncaught* when PyErr_Print() is called to
print it... That's what happens at the interactive prompt, of course,
and in your C code.

Looking at python source code, PyErr_Print() is actually a single call
to PyErr_PrintEx(1), the parameter (1) is named "set_sys_last_vars"
(aha!). You should try to call PyErr_PrintEx(0) instead, and see if this
improves something.

Then a documentation path will be very welcomed ;-)
History
Date User Action Args
2022-04-11 14:56:36adminsetgithub: 47578
2010-04-29 17:40:15terry.reedysetstatus: pending -> closed
2008-07-09 22:02:36amaury.forgeotdarcsetstatus: open -> pending
resolution: works for me
messages: + msg69490
2008-07-09 18:42:03dominic.lavoiesetfiles: + issue3328.zip
messages: + msg69481
2008-07-09 18:21:04dominic.lavoiesetmessages: + msg69480
2008-07-09 17:06:38amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg69475
2008-07-09 16:48:51dominic.lavoiecreate