views:

74

answers:

1

I have an application where I'm embedding python. It was developed on windows where it works fine, but now I'm porting it to linux with less success where it crashes in Py_Initialize(). From gdb, it seems to happen when loading the os module.

gdb reports this callstack on seg fault:

#0  0x002384fc in import_submodule (mod=None, subname=0xb7d8a9bb "os", fullname=0xb7d8a9bb "os") at ../Python/import.c:2551
#1  0x0023893c in load_next (mod=<value optimized out>, altmod=<value optimized out>, p_name=0xb7d8a9ac, buf=0xb7d8a9bb "os", p_buflen=0xb7d8a9b4) at ../Python/import.c:2411
//.... etc...:
#65 0x002439de in Py_Initialize () at ../Python/pythonrun.c:361

source code of import_submodule in Python/import.c (downloaded from 2.6.5 python):

static PyObject *
import_submodule(PyObject *mod, char *subname, char *fullname)
{ //***************** THIS IS LINE 2551***************************
    PyObject *modules = PyImport_GetModuleDict();
    PyObject *m = NULL;

    /* Require:
       if mod == None: subname == fullname
       else: mod.__name__ + "." + subname == fullname
    */

    if ((m = PyDict_GetItemString(modules, fullname)) != NULL) {
        Py_INCREF(m);
    }
    else {
        PyObject *path, *loader = NULL;
        char buf[MAXPATHLEN+1];
        struct filedescr *fdp;
        FILE *fp = NULL;

        if (mod == Py_None)
            path = NULL;
        else {
            path = PyObject_GetAttrString(mod, "__path__");
            if (path == NULL) {
                PyErr_Clear();
                Py_INCREF(Py_None);
                return Py_None;
            }
        }

        buf[0] = '\0';
        fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
                  &fp, &loader);
        Py_XDECREF(path);
        if (fdp == NULL) {
            if (!PyErr_ExceptionMatches(PyExc_ImportError))
                return NULL;
            PyErr_Clear();
            Py_INCREF(Py_None);
            return Py_None;
        }
        m = load_module(fullname, fp, buf, fdp->type, loader);
        Py_XDECREF(loader);
        if (fp)
            fclose(fp);
        if (!add_submodule(mod, m, fullname, subname, modules)) {
            Py_XDECREF(m);
            m = NULL;
        }
    }

    return m;
}

Disassembly + part source + breakpoint:

2550    import_submodule(PyObject *mod, char *subname, char *fullname)
2551    {
   0x002384f0 <+0>: push   %ebp
   0x002384f1 <+1>: mov    %esp,%ebp
   0x002384f3 <+3>: sub    $0x1058,%esp
   0x002384f9 <+9>: mov    %ebx,-0xc(%ebp)
=> 0x002384fc <+12>:    call   0x174787 <__i686.get_pc_thunk.bx>
   0x00238501 <+17>:    add    $0x112af3,%ebx
   0x00238507 <+23>:    mov    %esi,-0x8(%ebp)
   0x0023850a <+26>:    mov    0x8(%ebp),%esi
   0x0023850d <+29>:    mov    %edi,-0x4(%ebp)
   0x00238510 <+32>:    mov    %eax,-0x102c(%ebp)
   0x00238516 <+38>:    mov    %edx,-0x1030(%ebp)
   0x0023851c <+44>:    mov    %gs:0x14,%eax

What's happening here? Apparently some code from libpython2.6.so is loaded and run.

+1  A: 

Try setting the Python home with Py_SetPythonHome before calling Py_Initialize. Start with hardcoded complete path to the python directory. Also make sure you are not mixing debug & release versions. Py_GetPath is a good API to see where all python is looking for modules - but dont know if it can be called before Py_Initialize.

   char pySearchPath[] = "/users/abc/Python26";
   Py_SetPythonHome(pySearchPath);
   Py_Initialize();
   PyRun_SimpleString("from time import time,ctime\n"
                     "print 'Today is',ctime(time())\n");
   cerr << Py_GetPath() << endl;
sambha
Py_SetPythonHome worked! Thanks! I think the crash line number may have been off a few lines.
Imbrondir