Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit