I've had little time for Cython lately and so refcount nanny development 
has been slow. But when development is going at this pace I figured it 
was better to upload what I had so it doesn't start bit-rotting on my disk.

It is NOT FINISHED, but the ideas and framework is mostly in place, it 
is just a matter of working out all the places it fails. I'll continue 
it myself when I get time, but feel free...

By default it is disabled and Cython works as before. To enable it:
  cd Cython/Runtime
  ./build.sh # yes, ugh! Let's deal with that when the rest is done
  cd ../..
  python runtests.py --refnanny ...

One can then get reference count errors for two reasons:
- Most likely: The required calls to __Pyx_GOTREF and __Pyx_GIVEREF is 
missing in a given situation
- Otherwise: There's a genuine reference counting problem.

Here's the details:
- Cython generates code that can always be run with or without the 
refnanny -- to run it with, compile the C code with CYTHON_REFNANNY defined.
- Some boilerplate code is added when entering and exiting all functions 
(which should compile into nothing when not using the nanny)
- Many calls to Py_INCREF etc. are replaced with __Pyx_INCREF etc. (but 
not in utility code which is in general trusted and doesn't use the nanny)
- New calls are added: __Pyx_GOTREF, __Pyx_GIVEREF, __Pyx_XGIVEREF which 
are called after getting a reference from another function and before 
giving away a reference to a function/array/struct field. I.e:

__Pyx_GIVEREF(obj)
PyList_SET_ITEM(..., obj, ...)

and

obj = Py_Get...
if (!obj) { ... }
__Pyx_GOTREF(obj)

(Also, XGIVEREF is called on __pyx_r prior to returning.)

- There's a hook module in Cython/Runtime/refnanny.pyx. For now this is 
manually compiled with a Linux-only shell script, this must of course be 
done something about. See [1] for more plans for this module.
- runtests.py has the --refnanny flag to turn on the refnanny (when it 
is done, I expect this to be the default). What this does is loading the 
hook module and compiling modules with CYTHON_REFNANNY defined.

End result:
- Extra decrefs are intercepted and only logged.
- Functions continue as normal when this happen, but when the function 
returns for any reason a normal exception is raised if there's a leak or 
there was an extra decref somewhere.

[1] The module can be written to contain as advanced diagnostics as we 
like, and can be inspected by runtests.py to read logs etc.. It would be 
entirely possible to extend this to allow, say, putting assertions on 
the refcount operations Cython code performs in the doctests that 
runtests.py runs:

def f():
   """
   Test that this functions does the reference counting we would like.

   >>> import refnanny
   >>> a = 2
   >>> refnanny.monitor_object(a)
   >>> f(a)
   >>> print refnanny.operations_on(a)
   INCREFS=10, DECREFS=10
   """
   # ...

That's an argument for keeping it as a seperate module, but that's all 
I'm going to do about it for now.

Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to