Author: Armin Rigo <ar...@tunes.org>
Branch: cffi-static-callback-embedding
Changeset: r81508:381dbfd502eb
Date: 2015-12-30 18:31 +0100
http://bitbucket.org/pypy/pypy/changeset/381dbfd502eb/

Log:    revert some changes, and roughly finish the logic. Need to think
        about how to test that

diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -10,6 +10,8 @@
 from rpython.config.config import ConflictConfigError
 from pypy.tool.option import make_objspace
 from pypy.conftest import pypydir
+from rpython.rlib import rthread
+from pypy.module.thread import os_thread
 
 thisdir = py.path.local(__file__).dirpath()
 
@@ -76,8 +78,107 @@
                 return 1
         return exitcode
 
-    from pypy.interpreter import embedding
-    return entry_point, embedding.capture(space, debug)
+    # register the minimal equivalent of running a small piece of code. This
+    # should be used as sparsely as possible, just to register callbacks
+
+    from rpython.rlib.entrypoint import entrypoint_highlevel
+    from rpython.rtyper.lltypesystem import rffi, lltype
+
+    @entrypoint_highlevel('main', [rffi.CCHARP, rffi.INT],
+                          c_name='pypy_setup_home')
+    def pypy_setup_home(ll_home, verbose):
+        from pypy.module.sys.initpath import pypy_find_stdlib
+        verbose = rffi.cast(lltype.Signed, verbose)
+        if ll_home:
+            home1 = rffi.charp2str(ll_home)
+            home = os.path.join(home1, 'x') # <- so that 'll_home' can be
+                                            # directly the root directory
+        else:
+            home = home1 = pypydir
+        w_path = pypy_find_stdlib(space, home)
+        if space.is_none(w_path):
+            if verbose:
+                debug("pypy_setup_home: directories 'lib-python' and 
'lib_pypy'"
+                      " not found in '%s' or in any parent directory" % home1)
+            return rffi.cast(rffi.INT, 1)
+        space.startup()
+        space.appexec([w_path], """(path):
+            import sys
+            sys.path[:] = path
+        """)
+        # import site
+        try:
+            space.setattr(space.getbuiltinmodule('sys'),
+                          space.wrap('executable'),
+                          space.wrap(home))
+            import_ = space.getattr(space.getbuiltinmodule('__builtin__'),
+                                    space.wrap('__import__'))
+            space.call_function(import_, space.wrap('site'))
+            return rffi.cast(rffi.INT, 0)
+        except OperationError, e:
+            if verbose:
+                debug("OperationError:")
+                debug(" operror-type: " + e.w_type.getname(space))
+                debug(" operror-value: " + 
space.str_w(space.str(e.get_w_value(space))))
+            return rffi.cast(rffi.INT, -1)
+
+    @entrypoint_highlevel('main', [rffi.CCHARP], c_name='pypy_execute_source')
+    def pypy_execute_source(ll_source):
+        return pypy_execute_source_ptr(ll_source, 0)
+
+    @entrypoint_highlevel('main', [rffi.CCHARP, lltype.Signed],
+                          c_name='pypy_execute_source_ptr')
+    def pypy_execute_source_ptr(ll_source, ll_ptr):
+        source = rffi.charp2str(ll_source)
+        res = _pypy_execute_source(source, ll_ptr)
+        return rffi.cast(rffi.INT, res)
+
+    @entrypoint_highlevel('main', [], c_name='pypy_init_threads')
+    def pypy_init_threads():
+        if not space.config.objspace.usemodules.thread:
+            return
+        os_thread.setup_threads(space)
+
+    @entrypoint_highlevel('main', [], c_name='pypy_thread_attach')
+    def pypy_thread_attach():
+        if not space.config.objspace.usemodules.thread:
+            return
+        os_thread.setup_threads(space)
+        os_thread.bootstrapper.acquire(space, None, None)
+        # XXX this doesn't really work.  Don't use os.fork(), and
+        # if your embedder program uses fork(), don't use any PyPy
+        # code in the fork
+        rthread.gc_thread_start()
+        os_thread.bootstrapper.nbthreads += 1
+        os_thread.bootstrapper.release()
+
+    def _pypy_execute_source(source, c_argument):
+        try:
+            w_globals = space.newdict(module=True)
+            space.setitem(w_globals, space.wrap('__builtins__'),
+                          space.builtin_modules['__builtin__'])
+            space.setitem(w_globals, space.wrap('c_argument'),
+                          space.wrap(c_argument))
+            space.appexec([space.wrap(source), w_globals], """(src, glob):
+                import sys
+                stmt = compile(src, 'c callback', 'exec')
+                if not hasattr(sys, '_pypy_execute_source'):
+                    sys._pypy_execute_source = []
+                sys._pypy_execute_source.append(glob)
+                exec stmt in glob
+            """)
+        except OperationError, e:
+            debug("OperationError:")
+            debug(" operror-type: " + e.w_type.getname(space))
+            debug(" operror-value: " + 
space.str_w(space.str(e.get_w_value(space))))
+            return -1
+        return 0
+
+    return entry_point, {'pypy_execute_source': pypy_execute_source,
+                         'pypy_execute_source_ptr': pypy_execute_source_ptr,
+                         'pypy_init_threads': pypy_init_threads,
+                         'pypy_thread_attach': pypy_thread_attach,
+                         'pypy_setup_home': pypy_setup_home}
 
 
 # _____ Define and setup target ___
diff --git a/pypy/interpreter/embedding.py b/pypy/interpreter/embedding.py
deleted file mode 100644
--- a/pypy/interpreter/embedding.py
+++ /dev/null
@@ -1,173 +0,0 @@
-from rpython.rtyper.lltypesystem import rffi, lltype
-
-
-def capture(space, debug):
-    from rpython.rlib.entrypoint import entrypoint_highlevel
-    from rpython.rlib import rthread
-    from pypy.module.thread import os_thread
-    from pypy.conftest import pypydir
-    from pypy.module.sys.initpath import pypy_find_stdlib
-
-    @entrypoint_highlevel('main', [rffi.CCHARP, rffi.INT],
-                          c_name='pypy_setup_home')
-    def pypy_setup_home(ll_home, verbose):
-        _declare_c_function()
-        verbose = rffi.cast(lltype.Signed, verbose)
-        if ll_home:
-            home1 = rffi.charp2str(ll_home)
-            home = os.path.join(home1, 'x') # <- so that 'll_home' can be
-                                            # directly the root directory
-        else:
-            home = home1 = pypydir
-        w_path = pypy_find_stdlib(space, home)
-        if space.is_none(w_path):
-            if verbose:
-                debug("pypy_setup_home: directories 'lib-python' and 
'lib_pypy'"
-                      " not found in '%s' or in any parent directory" % home1)
-            return rffi.cast(rffi.INT, 1)
-        space.startup()
-        space.appexec([w_path], """(path):
-            import sys
-            sys.path[:] = path
-        """)
-        # import site
-        try:
-            space.setattr(space.getbuiltinmodule('sys'),
-                          space.wrap('executable'),
-                          space.wrap(home))
-            import_ = space.getattr(space.getbuiltinmodule('__builtin__'),
-                                    space.wrap('__import__'))
-            space.call_function(import_, space.wrap('site'))
-            return rffi.cast(rffi.INT, 0)
-        except OperationError, e:
-            if verbose:
-                debug("OperationError:")
-                debug(" operror-type: " + e.w_type.getname(space))
-                debug(" operror-value: " + 
space.str_w(space.str(e.get_w_value(space))))
-            return rffi.cast(rffi.INT, -1)
-
-    @entrypoint_highlevel('main', [rffi.CCHARP], c_name='pypy_execute_source')
-    def pypy_execute_source(ll_source):
-        return pypy_execute_source_ptr(ll_source, 0)
-
-    @entrypoint_highlevel('main', [rffi.CCHARP, lltype.Signed],
-                          c_name='pypy_execute_source_ptr')
-    def pypy_execute_source_ptr(ll_source, ll_ptr):
-        source = rffi.charp2str(ll_source)
-        res = _pypy_execute_source(source, ll_ptr)
-        return rffi.cast(rffi.INT, res)
-
-    @entrypoint_highlevel('main', [], c_name='pypy_init_threads')
-    def pypy_init_threads():
-        if not space.config.objspace.usemodules.thread:
-            return
-        os_thread.setup_threads(space)
-
-    @entrypoint_highlevel('main', [], c_name='pypy_thread_attach')
-    def pypy_thread_attach():
-        if not space.config.objspace.usemodules.thread:
-            return
-        # XXX this doesn't really work.  Don't use os.fork(), and
-        # if your embedder program uses fork(), don't use any PyPy
-        # code in the fork
-        rthread.gc_thread_start()
-        os_thread.bootstrapper.nbthreads += 1
-
-    def _pypy_execute_source(source, c_argument):
-        try:
-            w_globals = space.newdict(module=True)
-            space.setitem(w_globals, space.wrap('__builtins__'),
-                          space.builtin_modules['__builtin__'])
-            space.setitem(w_globals, space.wrap('c_argument'),
-                          space.wrap(c_argument))
-            space.appexec([space.wrap(source), w_globals], """(src, glob):
-                import sys
-                stmt = compile(src, 'c callback', 'exec')
-                if not hasattr(sys, '_pypy_execute_source'):
-                    sys._pypy_execute_source = []
-                sys._pypy_execute_source.append(glob)
-                exec stmt in glob
-            """)
-        except OperationError, e:
-            debug("OperationError:")
-            debug(" operror-type: " + e.w_type.getname(space))
-            debug(" operror-value: " + 
space.str_w(space.str(e.get_w_value(space))))
-            return -1
-        return 0
-
-    entrypoints_dict = {'pypy_execute_source': pypy_execute_source,
-                        'pypy_execute_source_ptr': pypy_execute_source_ptr,
-                        'pypy_init_threads': pypy_init_threads,
-                        'pypy_thread_attach': pypy_thread_attach,
-                        'pypy_setup_home': pypy_setup_home}
-
-    return entrypoints_dict
-
-
-_declare_c_function = rffi.llexternal_use_eci(separate_module_sources=[
-"""
-#define PYPY_INIT_NO_THREADS   0x01
-#define PYPY_INIT_QUIET        0x02
-
-static char _pypy_init_ok = 0;
-static void _pypy_init_once_quiet(void);
-static void _pypy_init_once_verbose(void);
-
-
-#ifndef _MSC_VER   /* --- Posix version --- */
-
-static char *guess_home(void)
-{
-    Dl_info info;
-    if (dladdr(&guess_home, &info) == 0)
-        return NULL;
-    return realpath(info.dli_fname, NULL);
-}
-
-RPY_EXPORTED
-int pypy_initialize(int flags)
-{
-    static pthread_once_t once_control_1 = PTHREAD_ONCE_INIT;
-    static pthread_once_t once_control_2 = PTHREAD_ONCE_INIT;
-
-    pthread_once(&once_control_1,
-                 (flags & PYPY_INIT_QUIET) ? _pypy_init_once_quiet
-                                           : _pypy_init_once_verbose);
-
-    if (_pypy_init_ok && (flags & PYPY_INIT_NO_THREADS) == 0)
-        pthread_once(&once_control_2, pypy_init_threads);
-
-    return _pypy_init_ok ? 0 : -1;
-}
-
-#else            /* --- Windows version --- */
-
-   XXX
-
-#endif
-
-
-static void _pypy_init_once(int verbose)
-{
-    char *home;
-    int verbose;
-    rpython_startup_code();
-
-    home = guess_home();
-    if (home == NULL)
-        return;
-    _pypy_init_ok = !pypy_setup_home(home, verbose);
-    free(home);
-}
-
-static void _pypy_init_once_quiet(void)
-{
-    _pypy_init_once(0);
-}
-
-static void _pypy_init_once_verbose(void)
-{
-    _pypy_init_once(1);
-}
-"""
-])
diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -68,7 +68,6 @@
     def startup(self, space):
         from pypy.module._cffi_backend import cffi1_module
         cffi1_module.glob.space = space
-        cffi1_module.declare_c_function()
 
 
 def get_dict_rtld_constants():
diff --git a/pypy/module/_cffi_backend/cffi1_module.py 
b/pypy/module/_cffi_backend/cffi1_module.py
--- a/pypy/module/_cffi_backend/cffi1_module.py
+++ b/pypy/module/_cffi_backend/cffi1_module.py
@@ -62,21 +62,29 @@
                                          ('code', rffi.CCHARP)))
 
 def load_embedded_cffi_module(space, version, init_struct):
-    name = rffi.charp2str(init_struct.name)
+    from pypy.module._cffi_backend.embedding import declare_c_function
+    declare_c_function()     # translation-time hint only:
+                             # declare _cffi_carefully_make_gil()
+    #
+    version = rffi.cast(lltype.Signed, version)
     if not (VERSION_MIN <= version <= VERSION_MAX):
         raise oefmt(space.w_ImportError,
-            "cffi *embedded* module '%s' has unknown version %s",
-            name, hex(version))
+            "cffi embedded module has got unknown version tag %s",
+            hex(version))
+    #
+    if space.config.objspace.usemodules.thread:
+        from pypy.module.thread import os_thread
+        os_thread.setup_threads(space)
+    #
+    name = rffi.charp2str(init_struct.name)
     module = load_cffi1_module(space, name, None, init_struct.func)
-    #
     code = rffi.charp2str(init_struct.code)
     compiler = space.createcompiler()
-    pycode = compiler.compile(code, "<init code for '%s'>" % name,
-                              'exec', 0)
+    pycode = compiler.compile(code, "<init code for '%s'>" % name, 'exec', 0)
     w_globals = module.getdict(space)
-    space.call_method(w_globals, "setdefault", "__builtins__",
-                      self.get_builtin())
-    pycode.exec_code(self, w_globals, w_globals)
+    space.call_method(w_globals, "setdefault", space.wrap("__builtins__"),
+                      space.wrap(space.builtin))
+    pycode.exec_code(space, w_globals, w_globals)
 
 
 class Global:
@@ -90,13 +98,20 @@
     try:
         init_struct = rffi.cast(INITSTRUCTPTR, init_struct)
         name = rffi.charp2str(init_struct.name)
-        version = rffi.cast(lltype.Signed, version)
+        #
+        space = glob.space
         try:
-            load_embedded_cffi_module(glob.space, version, init_struct)
+            load_embedded_cffi_module(space, version, init_struct)
             res = 0
         except OperationError, operr:
-            operr.write_unraisable(glob.space, "initialization of '%s'" % name,
+            operr.write_unraisable(space, "initialization of '%s'" % name,
                                    with_traceback=True)
+            space.appexec([], """():
+                import sys
+                sys.stderr.write('pypy version: %s.%s.%s\n' %
+                                 sys.pypy_version_info[:3])
+                sys.stderr.write('sys.path: %r\n' % (sys.path,))
+            """)
             res = -1
     except Exception, e:
         # oups! last-level attempt to recover.
diff --git a/pypy/module/_cffi_backend/embedding.py 
b/pypy/module/_cffi_backend/embedding.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_cffi_backend/embedding.py
@@ -0,0 +1,58 @@
+from rpython.rtyper.lltypesystem import rffi
+
+
+declare_c_function = rffi.llexternal_use_eci(separate_module_sources=[
+"""
+/* XXX Windows missing */
+#include <stdio.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+static unsigned char _cffi_ready = 0;
+static const char *volatile _cffi_module_name;
+
+static void _cffi_init_error(const char *msg, const char *extra)
+{
+    fprintf(stderr,
+            "\nPyPy initialization failure when loading module '%s':\n%s%s\n",
+            _cffi_module_name, msg, extra);
+}
+
+static void _cffi_init(void)
+{
+    Dl_info info;
+    char *home;
+
+    rpython_startup_code();
+
+    if (dladdr(&_cffi_init, &info) == 0) {
+        _cffi_init_error("dladdr() failed: ", dlerror());
+        return;
+    }
+    home = realpath(info.dli_fname, NULL);
+    if (pypy_setup_home(home, 1) != 0) {
+        _cffi_init_error("pypy_setup_home() failed", "");
+        return;
+    }
+
+    RPyGilAllocate();
+    RPyGilRelease();
+    _cffi_ready = 1;
+}
+
+RPY_EXPORTED
+int _cffi_carefully_make_gil(const char *name)
+{
+    /* For CFFI: this initializes the GIL and loads the home path.
+       It can be called completely concurrently from unrelated threads.
+       It assumes that we don't hold the GIL before (if it exists), and we
+       don't hold it afterwards.
+    */
+    static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+    _cffi_module_name = name;    /* not really thread-safe, but better than
+                                    nothing */
+    pthread_once(&once_control, _cffi_init);
+    return (int)_cffi_ready - 1;
+}
+"""])
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to