On Tuesday, 25 August 2015 23:27:35 David Naylor wrote:
> On Wednesday, 26 August 2015 00:09:14 Matti Picus wrote:
> > On 25/08/15 21:26, David Naylor wrote:
> >
> > 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
> >
> > I committed your patches as c2f97b8c2415, the last chunk looks strange
> > (why
> > standard_c_lib.__error.restype ? ) , but let's give it a shot and see what
> > happens. Matti
>
> The last chunk was unrelated to this change - it was just cleaning up
> references to FreeBSD.
>
> Although the tests now pass when run with python they still do not pass when
> run from pypy.
>
> It appears pypy does not properly handle ctypes.CDLL(name, handle=X) where X
> is an integer as returned by dlopen(3).  I have an idea on how to implement
> the fix but that will need to wait for tomorrow.

Please find attached for a patch that adds support for:
        ctypes.CDLL(name, handle=X)

The patch includes tests for the pypy and rpython changes.  I am not sure
about the policy regarding changes to the python libraries and thus did not
add a unit test there (the standard tests are lacking one for handle support
anyway).

I have translation tested the change and the previous fix I submitted now
works on pypy :-D.

I also filed an issue #2126 to clean up the handling of 'freebsd' for
sys.platform.

Lastly, regarding the segfault: it appears to be threading related.  I'll file
an issue detailing all the stack traces and anything else that I can find that
would be helpful.

Regards
--- lib-python/2.7/ctypes/__init__.py.orig	2015-05-31 07:19:51 UTC
+++ lib-python/2.7/ctypes/__init__.py
@@ -367,6 +367,8 @@ class CDLL(object):
                 self._handle = _ffi.CDLL(name, mode)
             else:
                 self._handle = _ffi.WinDLL(name, mode)
+        elif isinstance(handle, (int, long)):
+            self._handle = _ffi.CDLL(name, handle=handle)
         else:
             self._handle = handle

--- pypy/module/_rawffi/alt/interp_funcptr.py.orig	2015-05-31 07:19:51 UTC
+++ pypy/module/_rawffi/alt/interp_funcptr.py
@@ -9,7 +9,7 @@ from rpython.rtyper.lltypesystem import
 from rpython.rlib import jit
 from rpython.rlib import libffi
 from rpython.rlib.clibffi import get_libc_name, StackCheckError, LibFFIError
-from rpython.rlib.rdynload import DLOpenError
+from rpython.rlib.rdynload import DLLHANDLE, DLOpenError
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.objectmodel import we_are_translated
 from pypy.module._rawffi.alt.type_converter import FromAppLevelConverter, ToAppLevelConverter
@@ -314,7 +314,7 @@ W_FuncPtr.typedef = TypeDef(
 # =======================================================================
 class W_CDLL(W_Root):
-    def __init__(self, space, name, mode):
+    def __init__(self, space, name, mode, handle=rffi.cast(DLLHANDLE, 0)):
         self.flags = libffi.FUNCFLAG_CDECL
         self.space = space
         if name is None:
@@ -322,7 +322,7 @@ class W_CDLL(W_Root):
         else:
             self.name = name
         try:
-            self.cdll = libffi.CDLL(name, mode)
+            self.cdll = libffi.CDLL(name, mode, handle)
         except DLOpenError, e:
             raise wrap_dlopenerror(space, e, self.name)

@@ -339,9 +339,9 @@ class W_CDLL(W_Root):
                         "No symbol %s found in library %s", name, self.name)
         return space.wrap(address_as_uint)

-@unwrap_spec(name='str_or_None', mode=int)
-def descr_new_cdll(space, w_type, name, mode=-1):
-    return space.wrap(W_CDLL(space, name, mode))
+@unwrap_spec(name='str_or_None', mode=int, handle=int)
+def descr_new_cdll(space, w_type, name, mode=-1, handle=0):
+    return space.wrap(W_CDLL(space, name, mode, rffi.cast(DLLHANDLE, handle)))


 W_CDLL.typedef = TypeDef(
--- pypy/module/_rawffi/alt/test/test_funcptr.py.orig	2015-05-31 07:19:51 UTC
+++ pypy/module/_rawffi/alt/test/test_funcptr.py
@@ -643,3 +643,13 @@ class AppTestFFI(BaseAppTestFFI):
         f_name = libfoo.getfunc('AAA_first_ordinal_function', [], types.sint)
         f_ordinal = libfoo.getfunc(1, [], types.sint)
         assert f_name.getaddr() == f_ordinal.getaddr()
+
+    def test_handle(self):
+        if self.iswin32:
+            skip("unix specific")
+        from _rawffi.alt import CDLL, types
+        RTLD_DEFAULT = -2 # see <dlfcn.h>
+        libc = CDLL("<None>", handle=RTLD_DEFAULT)
+        isdigit = libc.getfunc('isdigit', [types.sint], types.sint)
+        res = isdigit(49)
+        assert res == 1
--- rpython/rlib/libffi.py.orig	2015-05-31 07:19:51 UTC
+++ rpython/rlib/libffi.py
@@ -414,14 +414,19 @@ class Func(AbstractFuncPtr):

 # XXX: it partially duplicate the code in clibffi.py
 class CDLL(object):
-    def __init__(self, libname, mode=-1):
+    def __init__(self, libname, mode=-1, handle=rffi.cast(DLLHANDLE, 0)):
         """Load the library, or raises DLOpenError."""
-        self.lib = rffi.cast(DLLHANDLE, 0)
-        with rffi.scoped_str2charp(libname) as ll_libname:
-            self.lib = dlopen(ll_libname, mode)
+        if handle != rffi.cast(DLLHANDLE, 0):
+            self.ismanaged = False
+            self.lib = handle
+        else:
+            self.ismanaged = False
+            self.lib = rffi.cast(DLLHANDLE, 0)
+            with rffi.scoped_str2charp(libname) as ll_libname:
+                self.lib = dlopen(ll_libname, mode)

     def __del__(self):
-        if self.lib:
+        if self.lib and self.ismanaged:
             dlclose(self.lib)
             self.lib = rffi.cast(DLLHANDLE, 0)

--- rpython/rlib/test/test_libffi.py.orig	2015-05-31 07:19:51 UTC
+++ rpython/rlib/test/test_libffi.py
@@ -625,5 +625,19 @@ class TestLibffiCall(BaseFfiTest):
             chain = ArgChain()
             assert 24 == f_by_ordinal.call(chain, lltype.Signed, is_structĂșlse)

-
-
+    else:
+        def test_handle(self):
+            """
+                RPY_EXPORTED
+                int add_xy(int x, int y)
+                {
+                    return x + y;
+                }
+            """
+            from rpython.rlib.rdynload import dlopen, dlclose
+            handle = dlopen(self.libfoo_name)
+            libfoo = CDLL("<None>", handle=handle)
+            func = (libfoo, 'add_xy', [types.sint, types.sint], types.sint)
+            res = self.call(func, [50, 8], lltype.Signed)
+            assert res == 58
+            dlclose(handle)

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