Author pitrou
Recipients pakal, pitrou
Date 2010-01-15.22:15:18
SpamBayes Score 2.53075e-11
Marked as misclassified No
Message-id <1263593783.25822.12.camel@localhost>
In-reply-to <1263590489.29.0.622751301386.issue6939@psf.upfronthosting.co.za>
Content
> posobj = portable_lseek(fd, posobj, 0); -> don't we lose the reference
> to the old "posobj" there, doing a memory leak ?

It's a bit more subtle.
Here, the first reference to "posobj" that you get is through the
function arguments. You don't own that reference, so must not decref it
when you are done with it. Moreover, if you return that very same
reference, you should incref it first (which your patch doesn't do when
posobj is non-None, and therefore loses a reference, see below).

However, when you get a new "posobj" from portable_lseek() (or most
other C API functions), you own this new reference and therefore must
decref it when you are done with it.

To sum it up and if I'm not mistaken, you must:
- add a Py_INCREF(posobj) when posobj is non-NULL and non-None.
- Py_DECREF the first posobj, as well as oldposobj, in the
Windows-specific path.

If you wanna witness reference counting behaviour, you should build
Python in debug mode (--with-pydebug if under Linux). Right now under
Linux your patch produces the following behaviour:

[39542 refs]
>>> f.truncate()
0L
[39547 refs]
>>> f.truncate()
0L
[39547 refs]
>>> f.truncate(2)
2
[39545 refs]
>>> f.truncate(2)
2
[39544 refs]

As you see, when posobj is non-None, we actually lose a reference
because a Py_INCREF is missing.
If you do this too often the small integer object "2" gets wrongly
destroyed and the interpreter crashes:

... 
[snip]
Erreur de segmentation
History
Date User Action Args
2010-01-15 22:15:21pitrousetrecipients: + pitrou, pakal
2010-01-15 22:15:19pitroulinkissue6939 messages
2010-01-15 22:15:18pitroucreate