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) *  |
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) *  |
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 ;-) |
|
|