On Monday, 24 August 2015 23:07:20 David Naylor wrote:
> On Saturday, 22 August 2015 21:25:44 Matti Picus wrote:
> > I would like to add the freebsd-9-x86-64 binary tgz to our released
> > downloads. We still have a number of failing tests showing up on
> > http://buildbot.pypy.org/summary?category=freebsd64
> > among them many
> > DLOpenError: "opening 'libm.so' with ctypes.CDLL() works, but not with
> > c_dlopen()??"
> > and the more worrying SIGSEGV in
> > http://buildbot.pypy.org/summary/longrepr?testname=unmodified&builder=pypy
> > -c -jit-freebsd-9-x86-64&builde5&mod=lib-python.2.7.test.test_io
> >
> > Could someone proficient in freebsd suggest what is going on?
>
> Hi Matti,
>
> I am able to reproduce this on FreeBSD 10.2:
> # cat > test.py << __EOF
> from ctypes import *
>
> libc = CDLL("libc.so.7")
> dlopen = libc["dlopen"]
>
> # see <dlfnc.h>: void    *dlopen(const char *, int);
> dlopen.argtypes = [c_char_p, c_int]
> dlopen.restype = c_void_p
>
> print dlopen(c_char_p("libm.so"), c_int(0))
> __EOF
> # python test.py
> None

I have found the root cause of this problem (from the FreeBSD-Python team):
"""
Because dlopen symbol is magic.  It is provided by the shared libc.so
to satisfy the static linker, but real definition comes from the dynamic
linker.  The libc.so dlopen() is a null stub.

You are asking for the dlopen symbol from libc, which is returned to
you in faith, and which cannot load a library for real. While in the C
example, you use normal symbol resolution and get the dlopen from the
loader.

To get a handle to real dlopen with dlopen/dlsym, you should do in C:
        dlopenX = dlsym(RTLD_DEFAULT, "dlopen");
""" - Konstantin Belousov

Please find attached for a patch that fixes this issue.  Would you like me to
submit a bug report for this patch?

I have not translation tested this patch as yet.

Regards
--- rpython/rtyper/lltypesystem/ll2ctypes.py.orig	2015-05-31 07:19:51 UTC
+++ rpython/rtyper/lltypesystem/ll2ctypes.py
@@ -47,6 +47,7 @@ rlock = RLock()
 _POSIX = os.name == "posix"
 _MS_WINDOWS = os.name == "nt"
 _64BIT = "64bit" in host_platform.architecture()[0]
+_FREEBSD = sys.platform.startswith('freebsd')


 # ____________________________________________________________
@@ -1080,8 +1081,11 @@ if ctypes:
             return ctypes.util.find_library('c')

     libc_name = get_libc_name()     # Make sure the name is determined during import, not at runtime
+    if _FREEBSD:
+        RTLD_DEFAULT = -2  # see <dlfcn.h>
+        rtld_default_lib = ctypes.CDLL("RTLD_DEFAULT", handle=RTLD_DEFAULT, **load_library_kwargs)
     # XXX is this always correct???
-    standard_c_lib = ctypes.CDLL(get_libc_name(), **load_library_kwargs)
+    standard_c_lib = ctypes.CDLL(libc_name, **load_library_kwargs)

 # ____________________________________________

@@ -1173,7 +1177,10 @@ def get_ctypes_callable(funcptr, calling
                 not_found.append(libname)

     if cfunc is None:
-        cfunc = get_on_lib(standard_c_lib, funcname)
+        if _FREEBSD and funcname in ('dlopen', 'fdlopen', 'dlsym', 'dlfunc', 'dlerror', 'dlclose'):
+            cfunc = get_on_lib(rtld_default_lib, funcname)
+        else:
+            cfunc = get_on_lib(standard_c_lib, funcname)
         # XXX magic: on Windows try to load the function from 'kernel32' too
         if cfunc is None and hasattr(ctypes, 'windll'):
             cfunc = get_on_lib(ctypes.windll.kernel32, funcname)
@@ -1497,13 +1504,12 @@ else:
             def _where_is_errno():
                 return standard_c_lib._errno()

-        elif sys.platform.startswith('linux') or sys.platform == 'freebsd6':
+        elif sys.platform.startswith('linux'):
             standard_c_lib.__errno_location.restype = ctypes.POINTER(ctypes.c_int)
             def _where_is_errno():
                 return standard_c_lib.__errno_location()

-        elif any(plat in sys.platform
-                 for plat in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9')):
+        elif sys.platform == 'darwin' or sys.platform.startswith('freebsd'):
             standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int)
             def _where_is_errno():
                 return standard_c_lib.__error()

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
pypy-dev mailing list
pypy-dev@python.org
https://mail.python.org/mailman/listinfo/pypy-dev

Reply via email to