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
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