Skip to content

Nested ctypes calls using njit(cache=True) results in segmentation fault #3621

Closed

Description

@lespaul

Using numba 0.41.0 and python 2.7.12 on linux, I see that using 3 levels of function calls to reach a ctypes function call results in a segmentation fault when using njit(cache=True). The first run on the python file runs fine as expected; however, when run the second time with the cached files present, a segmentation fault occurs. Interestingly, when reducing the code to use only 2 function calls to reach the ctypes function, everything works perfectly fine.

compiled using clang++ 8.0.0:
clang++ -O3 -std=c++17 -fPIC -shared crash.cpp -o /tmp/libcrash.so

crash.hpp

extern "C"
{
    double e();
}

crash.cpp

#include "crash.hpp"

double e()
{
    return 1.0;
}

crash.py

from numba import njit
import ctypes

libcrash = ctypes.CDLL("/tmp/libcrash.so")
c_func = libcrash.e
c_func.argtypes = []
c_func.restype = ctypes.c_double

@njit(cache=True)
def c():
    return c_func()

@njit(cache=True)
def b():
    return c()

@njit()
def a(cache=True):
    return b()

print a()

Activity

  1. changed the title [-]Nested ctypes calls in njit[/-] [+]Nested ctypes calls using njit(cache=True) results in segmentation fault[/+] on Dec 20, 2018
  2. lespaul commented on Dec 20, 2018

    @lespaul
    Author

    Here is a backtrace from gdb which probably isn't helpful but just in case

    #0  0x00007f0691ffd690 in ?? ()
    #1  0x00007f389b1c406d in cpython::__main__::a$241(omitted$28default$3dTrue$29) ()
    #2  0x00007f389b1dbcdc in call_cfunc (locals=0x0 <numba.dynamic.globals.7f0691ffd690>,
        kws=0x0 <numba.dynamic.globals.7f0691ffd690>, args=0x7f389772b6d0, cfunc=0x7f388b7277e8, self=0x7f388d0780d0)
        at numba/_dispatcher.c:343
    #3  compile_and_invoke (self=self@entry=0x7f388d0780d0, args=args@entry=0x7f389772b6d0,
        kws=kws@entry=0x0 <numba.dynamic.globals.7f0691ffd690>,
        locals=locals@entry=0x0 <numba.dynamic.globals.7f0691ffd690>) at numba/_dispatcher.c:366
    #4  0x00007f389b1dc40d in Dispatcher_call (self=0x7f388d0780d0, args=<optimized out>, kws=<optimized out>)
        at numba/_dispatcher.c:572
    #5  0x00007f3898418273 in PyObject_Call () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #6  0x00007f38983b635c in PyEval_EvalFrameEx () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #7  0x00007f38984ef05c in PyEval_EvalCodeEx () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #8  0x00007f38983b0da9 in PyEval_EvalCode () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #9  0x00007f38983b705b in PyEval_EvalFrameEx () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #10 0x00007f38984ef05c in PyEval_EvalCodeEx () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #11 0x00007f38983b7f1d in PyEval_EvalFrameEx () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #12 0x00007f38984ef05c in PyEval_EvalCodeEx () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #13 0x00007f3898445370 in ?? () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #14 0x00007f3898418273 in PyObject_Call () from /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0
    #15 0x0000000001319246 in RunModule(char*, int) ()
    #16 0x0000000001318cf1 in main ()```
    
  3. stuartarchibald commented on Dec 20, 2018

    @stuartarchibald
    Contributor

    Thanks for the report. I can reproduce. Here's a reproducer binding to libm.

    from numba import njit, gdb_init
    import ctypes
    
    lib = ctypes.CDLL("libm.so.6")
    c_func = lib.cos
    c_func.argtypes = [ctypes.c_double]
    c_func.restype = ctypes.c_double
    
    @njit(cache=True)
    def c():
        return c_func(1.e0)
    
    @njit(cache=True)
    def b():
        return c()
    
    @njit()
    def a(cache=True):
        gdb_init('-ex', 'bt')
        return b()
    
    print(a())

    run with:

    $ NUMBA_OPT=0 NUMBA_DEBUGINFO=1  python issue3621.py 
    

    this is the top of the backtrace, seems like the signal comes from the ctype bound DSO function ptr.

    Program received signal SIGSEGV, Segmentation fault.
    0x00007f9473eae3c0 in ?? ()
    #0  0x00007f9473eae3c0 in ?? ()
    #1  0x00007f7ce05b135c in __main__::c$244 () at issue3621.py:11
    #2  0x00007f7ce05b104e in __main__::b$243 () at issue3621.py:15
    #3  0x00007f7ce05af17e in __main__::a$241(omitted$28default$3dTrue$29) () at issue3621.py:20
    #4  0x00007f7ce05af2dc in cpython::__main__::a$241(omitted$28default$3dTrue$29) ()
    #5  0x00007f7ce2bd66a4 in call_cfunc ()
    
  4. sklam commented on Dec 20, 2018

    @sklam
    Member

    The external function address reference should have disabled caching. That happened in the first layer but lost in the higher layers.

  5. sklam commented on Dec 20, 2018

    @sklam
    Member

    So, there's a fix to make it properly disable caching. But, I think users also want a way to reference pre-compiled external function and have the numba function still be cache-able.

  6. added a commit that references this issue on Dec 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions