segmentation fault in assignment unpack a,b,c=a

Bug #183765 reported by Alon Levy
2
Affects Status Importance Assigned to Milestone
Cython
Fix Committed
Medium
Unassigned

Bug Description

Hi,

 First of all, I'm happy with cython (and pyrex for that matter), and it has been giving me a lot for very little work, for which I am grateful.

 The problem itself: I have a simple unpack statement and am getting a segmentation fault there. Using gdb I pinpointed the problem code, I think. Here is the pyx source:

def test(n1):
    n1,n2,x=n1

test((1,2,3))

My setup:
 ubuntu hardy (alpha 3 at this point I think)
 64bit (core 2 quad)
 python 2.5.1 (ubuntu package)
 cython from repository of today (revision 194)

The crux is that a variable containing the tuple is reused as one of the items in that tuple. The c code then tries to access it as a tuple again. The actual segmentation fault is raised in the line indicated by "segfault here"

130 /* "/home/alon/src/cython_tests/unpackbug.pyx":2
131 * def test(n1):
132 * n1,n2,x=n1 # <<<<<<<<<<<<<<
133 *
134 * test((1,2,3))
(gdb)
135 */
136 if (PyTuple_CheckExact(__pyx_v_n1) && PyTuple_GET_SIZE(__pyx_v_n1) == 3) {
137 __pyx_2 = PyTuple_GET_ITEM(__pyx_v_n1, 0);
138 Py_INCREF(__pyx_2);
139 Py_DECREF(__pyx_v_n1); // <----------------------------- error - pyx_v_n1 is being used in line 142, shouldn't be decreffed.
140 __pyx_v_n1 = __pyx_2; // <----------------------------- error2 (same cause probably) - why is it being reused?
141 __pyx_2 = 0;
142 __pyx_2 = PyTuple_GET_ITEM(__pyx_v_n1, 1);
143 Py_INCREF(__pyx_2);
144 Py_DECREF(__pyx_v_n2);
(gdb)
145 __pyx_v_n2 = __pyx_2;
146 __pyx_2 = 0;
147 __pyx_2 = PyTuple_GET_ITEM(__pyx_v_n1, 2);
148 Py_INCREF(__pyx_2); // <----------------------------------------- segfault here
149 Py_DECREF(__pyx_v_x);
150 __pyx_v_x = __pyx_2;
151 __pyx_2 = 0;
152 }

So I'm going to do a simple workaround -
tmp = n1
n1,n2,x=tmp

and hope it works.

Alon
p.s. Attaching the source shortly (hope launchpad let's you do that).
p.p.s this doesn't happen at the module level, you have to put it in a function. The generated code is different for a module.
p.p.p.s just in case:

# unpackbug.pyx
def test(n1):
    n1,n2,x=n1

test((1,2,3))

# setup.py
from distutils.extension import Extension
from Cython.Distutils import build_ext

import sys, os

setup(
  name = 'cython_unpackbug',
  ext_modules=[
    Extension("unpackbug", ["unpackbug.pyx"]),
  ],
  cmdclass = {'build_ext': build_ext},
)

# Makefile (if you copy and paste don't forget to replace spaces with tabs at line start)
all:
 python setup.py build_ext --inplace

test:
 python -c "import unpackbug"

Revision history for this message
Alon Levy (alonlevy1) wrote :

source to reproduce segmentation fault.

Revision history for this message
scoder (scoder) wrote :

This is an unusual use case, however, having the generated code crash is clearly a bug.

I think the right thing to do would be to generate code that works as you describe the work around: keep the tuple in a temp variable, do the assignments from the temp var, and decref the temp variable afterwards.

Changed in cython:
importance: Undecided → Medium
status: New → Confirmed
Revision history for this message
scoder (scoder) wrote :
Revision history for this message
Alon Levy (alonlevy1) wrote :

Well, I wouldn't say that unusual. At least, I encountered it in networkx code (which is in sage afaik), while cythoning it to remove this bottleneck from my app. It's in multiple places there, used in add_edge (this is where I got the segfault) in both GraphX and DiGraphX, so you can provide arguments seperatly or as a single tuple. (the following is from memory):
def add_edge(n1, n2=None, x=None):
    if n2 is None:
        if len(n1) == 3:
            n1, n2, x = n1
        else:
            n1, n2 = n1

scoder (scoder)
Changed in cython:
status: Confirmed → Fix Committed
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.