Search code examples
pythondistutilspython-c-extension

Segmentation fault on calling Python C-extension module


I have a C extension module that I am building and using on CentOS using distutils .

python setup.py build_ext --inplace

However the moment I try to use the same (recompiling again of course to generate the .so file) in a 64 bit Ubuntu machine I am getting a segmentation fault on the invocation of the c-module.

I am using Python 2.7.

Running it using gdb I am getting the following trace

[Switching to Thread 0x7ffff232f700 (LWP 4685)]
convertsimple (freelist=0x7ffff232c840, bufsize=256, msgbuf=0x7ffff232c8d0 "", flags=0, 
p_va=0x54a812, p_format=<synthetic pointer>, arg=0x808430) at Python/getargs.c:716
716 Python/getargs.c: No such file or directory.

Note the same code works fine in CentOS 64 bit when I compile the extension module and use it there.

GDB BKtrace

(gdb) bt
#0  convertsimple (freelist=0x7ffff232b820, bufsize=256, msgbuf=0x7ffff232b8b0 "\250", 
    flags=-72515583, p_va=0x7ffff232b920, p_format=<synthetic pointer>, arg=0x808430)
    at Python/getargs.c:716
#1  convertitem (arg=0x808430, p_format=p_format@entry=0x7ffff232b818, 
    p_va=p_va@entry=0x7ffff232ba08, flags=flags@entry=0, 
    levels=levels@entry=0x7ffff232b830, msgbuf=msgbuf@entry=0x7ffff232b8b0 "\250", 
    bufsize=bufsize@entry=256, freelist=freelist@entry=0x7ffff232b820)
    at Python/getargs.c:514
#2  0x00000000004c8cb2 in vgetargs1 (args=0x7fffe80475f0, format=0x7ffff2582b70 "is#i", 
    p_va=p_va@entry=0x7ffff232ba08, flags=flags@entry=0) at Python/getargs.c:345
#3  0x00000000004c8fc9 in PyArg_ParseTuple (args=args@entry=0x7fffe80475f0, 
    format=format@entry=0x7ffff2582b70 "is#i") at Python/getargs.c:85
#4  0x00007ffff2581dd3 in cbmsg_parse (self=<optimized out>, args=0x7fffe80475f0)
    at src/cbmsgmodule_v1.c:44
#5  0x00000000004b5816 in call_function (oparg=<optimized out>, pp_stack=0x7ffff232bc30)
    at Python/ceval.c:4021

Solution

  • So, finally found out the bug; It was a coding mistake in parsing the argument, for a python buffer which has null values ,I put the format specifier as "is#i" and passed in an integer from Python code to denote the length of the string; How ever the correct specifier is "is#" ; and you don't need to pass in the length explicitly from python; but in C you need to provide the address of a integer for the PyArg_ParseTuple to decode the lenght to.

    So basically with my code I was writing into a memory I did not allocate and on one OS nothing happened because of sheer luck or the way memory was allocated by some previous buffer and RAM availability, but it had a problem on Ubuntu and correctly.

    Lesson - when you do low level programming touching C etc, be extra careful about memory allocation and freeing. It is always a headache if missed