[pypy-commit] pypy ffi-backend: Change cerrno to be thread-safe.

arigo noreply at buildbot.pypy.org
Thu Jul 26 23:15:57 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r56487:2e0907ceb229
Date: 2012-07-26 23:15 +0200
http://bitbucket.org/pypy/pypy/changeset/2e0907ceb229/

Log:	Change cerrno to be thread-safe.

diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -150,7 +150,7 @@
     ll_userdata - a special structure which holds necessary information
                   (what the real callback is for example), casted to VOIDP
     """
-    cerrno.save_errno()
+    e = cerrno.get_real_errno()
     ll_res = rffi.cast(rffi.CCHARP, ll_res)
     unique_id = rffi.cast(lltype.Signed, ll_userdata)
     callback = global_callback_mapping.get(unique_id)
@@ -168,7 +168,10 @@
                               SIZE_OF_FFI_ARG * llmemory.sizeof(lltype.Char))
         return
     #
+    ec = None
     try:
+        ec = cerrno.get_errno_container(callback.space)
+        cerrno.save_errno_into(ec, e)
         try:
             callback.invoke(ll_args, ll_res)
         except OperationError, e:
@@ -185,4 +188,5 @@
         except OSError:
             pass
         callback.write_error_return_value(ll_res)
-    cerrno.restore_errno()
+    if ec is not None:
+        cerrno.restore_errno_from(ec)
diff --git a/pypy/module/_cffi_backend/cerrno.py b/pypy/module/_cffi_backend/cerrno.py
--- a/pypy/module/_cffi_backend/cerrno.py
+++ b/pypy/module/_cffi_backend/cerrno.py
@@ -1,24 +1,29 @@
 from pypy.rlib import rposix
+from pypy.interpreter.executioncontext import ExecutionContext
 from pypy.interpreter.gateway import unwrap_spec
 
 
-class ErrnoContainer(object):
-    # XXXXXXXXXXXXXX! thread-safety
-    errno = 0
+ExecutionContext._cffi_saved_errno = 0
 
-errno_container = ErrnoContainer()
 
+def get_errno_container(space):
+    return space.getexecutioncontext()
 
-def restore_errno():
-    rposix.set_errno(errno_container.errno)
+get_real_errno = rposix.get_errno
 
-def save_errno():
-    errno_container.errno = rposix.get_errno()
+
+def restore_errno_from(ec):
+    rposix.set_errno(ec._cffi_saved_errno)
+
+def save_errno_into(ec, errno):
+    ec._cffi_saved_errno = errno
 
 
 def get_errno(space):
-    return space.wrap(errno_container.errno)
+    ec = get_errno_container(space)
+    return space.wrap(ec._cffi_saved_errno)
 
 @unwrap_spec(errno=int)
 def set_errno(space, errno):
-    errno_container.errno = errno
+    ec = get_errno_container(space)
+    ec._cffi_saved_errno = errno
diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py
--- a/pypy/module/_cffi_backend/ctypefunc.py
+++ b/pypy/module/_cffi_backend/ctypefunc.py
@@ -142,12 +142,14 @@
                 argtype.convert_from_object(data, w_obj)
             resultdata = rffi.ptradd(buffer, cif_descr.exchange_result)
 
-            cerrno.restore_errno()
+            ec = cerrno.get_errno_container(space)
+            cerrno.restore_errno_from(ec)
             clibffi.c_ffi_call(cif_descr.cif,
                                rffi.cast(rffi.VOIDP, funcaddr),
                                resultdata,
                                buffer_array)
-            cerrno.save_errno()
+            e = cerrno.get_real_errno()
+            cerrno.save_errno_into(ec, e)
 
             if self.ctitem.is_primitive_integer:
                 if BIG_ENDIAN:


More information about the pypy-commit mailing list