[pypy-svn] r46589 - in pypy/dist/pypy/module/thread: . test
arigo at codespeak.net
arigo at codespeak.net
Fri Sep 14 20:29:04 CEST 2007
Author: arigo
Date: Fri Sep 14 20:29:04 2007
New Revision: 46589
Added:
pypy/dist/pypy/module/thread/error.py (contents, props changed)
Modified:
pypy/dist/pypy/module/thread/gil.py
pypy/dist/pypy/module/thread/ll_thread.py
pypy/dist/pypy/module/thread/os_lock.py
pypy/dist/pypy/module/thread/os_thread.py
pypy/dist/pypy/module/thread/test/test_thread.py
Log:
Fix error handling (at least, attempt to).
Note that there is a race condition somewhere on top of py.py
making test_local crash but very rarely :-((
Added: pypy/dist/pypy/module/thread/error.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/thread/error.py Fri Sep 14 20:29:04 2007
@@ -0,0 +1,6 @@
+from pypy.interpreter.error import OperationError
+
+def reraise_thread_error(space, msg):
+ w_module = space.getbuiltinmodule('thread')
+ w_error = space.getattr(w_module, space.wrap('error'))
+ raise OperationError(w_error, space.wrap(msg))
Modified: pypy/dist/pypy/module/thread/gil.py
==============================================================================
--- pypy/dist/pypy/module/thread/gil.py (original)
+++ pypy/dist/pypy/module/thread/gil.py Fri Sep 14 20:29:04 2007
@@ -8,6 +8,7 @@
# from time to time, using the executioncontext's XXX
from pypy.module.thread import ll_thread as thread
+from pypy.module.thread.error import reraise_thread_error
from pypy.interpreter.miscutils import Action
from pypy.module.thread.threadlocals import OSThreadLocals
from pypy.rlib.objectmodel import invoke_around_extcall
@@ -19,7 +20,10 @@
def setup_threads(self, space):
"""Enable threads in the object space, if they haven't already been."""
if self.GIL is None:
- self.GIL = thread.allocate_lock_NOAUTO()
+ try:
+ self.GIL = thread.allocate_lock_NOAUTO()
+ except thread.error:
+ reraise_thread_error(space, "can't allocate GIL")
self.enter_thread(space) # setup the main thread
# add the GIL-releasing callback as an action on the space
space.pending_actions.append(GILReleaseAction(self))
Modified: pypy/dist/pypy/module/thread/ll_thread.py
==============================================================================
--- pypy/dist/pypy/module/thread/ll_thread.py (original)
+++ pypy/dist/pypy/module/thread/ll_thread.py Fri Sep 14 20:29:04 2007
@@ -11,11 +11,8 @@
from pypy.annotation import model as annmodel
from pypy.rpython.lltypesystem.lltype import typeOf
from pypy.rlib.objectmodel import debug_assert
-from pypy.rlib.nonconst import NonConstant
-class error(Exception):
- def __init__(self, msg):
- self.msg = msg
+error = thread.error
from pypy.tool.autopath import pypydir
pypydir = py.path.local(pypydir)
@@ -138,7 +135,7 @@
# Sanity check: the lock must be locked
if self.acquire(False):
c_thread_releaselock(self._lock)
- raise error(NonConstant("bad lock"))
+ raise error("bad lock")
else:
c_thread_releaselock(self._lock)
Modified: pypy/dist/pypy/module/thread/os_lock.py
==============================================================================
--- pypy/dist/pypy/module/thread/os_lock.py (original)
+++ pypy/dist/pypy/module/thread/os_lock.py Fri Sep 14 20:29:04 2007
@@ -3,7 +3,7 @@
"""
from pypy.module.thread import ll_thread as thread
-from pypy.interpreter.error import OperationError
+from pypy.module.thread.error import reraise_thread_error
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.gateway import ObjSpace, interp2app
from pypy.interpreter.typedef import TypeDef
@@ -29,9 +29,11 @@
class Lock(Wrappable):
"A wrappable box around an interp-level lock object."
- def __init__(self):
- # XXX catch thread.error!
- self.lock = thread.allocate_lock()
+ def __init__(self, space):
+ try:
+ self.lock = thread.allocate_lock()
+ except thread.error:
+ reraise_thread_error(space, "out of resources")
def descr_lock_acquire(self, space, waitflag=1):
"""Lock the lock. Without argument, this blocks if the lock is already
@@ -51,9 +53,7 @@
try:
self.lock.release()
except thread.error:
- w_module = space.getbuiltinmodule('thread')
- w_error = space.getattr(w_module, space.wrap('error'))
- raise OperationError(w_error, space.wrap("release unlocked lock"))
+ reraise_thread_error(space, "release unlocked lock")
def descr_lock_locked(self, space):
"""Return whether the lock is in the locked state."""
@@ -96,7 +96,7 @@
def allocate_lock(space):
"""Create a new lock object. (allocate() is an obsolete synonym.)
See LockType.__doc__ for information about locks."""
- return space.wrap(Lock())
+ return space.wrap(Lock(space))
def getlocktype(space):
return space.gettypeobject(Lock.typedef)
Modified: pypy/dist/pypy/module/thread/os_thread.py
==============================================================================
--- pypy/dist/pypy/module/thread/os_thread.py (original)
+++ pypy/dist/pypy/module/thread/os_thread.py Fri Sep 14 20:29:04 2007
@@ -3,6 +3,7 @@
"""
from pypy.module.thread import ll_thread as thread
+from pypy.module.thread.error import reraise_thread_error
from pypy.interpreter.error import OperationError
from pypy.interpreter.gateway import NoneNotWrapped
from pypy.interpreter.gateway import ObjSpace, W_Root, Arguments
@@ -81,7 +82,10 @@
boot.space = space
boot.w_callable = w_callable
boot.args = args
- ident = thread.start_new_thread(Bootstrapper.bootstrap, (boot,))
+ try:
+ ident = thread.start_new_thread(Bootstrapper.bootstrap, (boot,))
+ except thread.error:
+ reraise_thread_error(space, "can't start new thread")
return space.wrap(ident)
Modified: pypy/dist/pypy/module/thread/test/test_thread.py
==============================================================================
--- pypy/dist/pypy/module/thread/test/test_thread.py (original)
+++ pypy/dist/pypy/module/thread/test/test_thread.py Fri Sep 14 20:29:04 2007
@@ -1,7 +1,31 @@
+import thread, time
from pypy.module.thread.test.support import GenericTestThread
class AppTestThread(GenericTestThread):
+ def setup_class(cls):
+ GenericTestThread.setup_class.im_func(cls)
+ # if we cannot start more than, say, 1000 threads on this OS, then
+ # we can check that we get the proper error at app-level
+ space = cls.space
+ lock = thread.allocate_lock()
+ lock.acquire()
+ def f():
+ lock.acquire()
+ lock.release()
+ try:
+ try:
+ for i in range(1000):
+ thread.start_new_thread(f, ())
+ finally:
+ lock.release()
+ # wait a bit to allow most threads to finish now
+ time.sleep(0.5)
+ except (thread.error, MemoryError):
+ cls.w_can_start_many_threads = space.w_False
+ else:
+ cls.w_can_start_many_threads = space.w_True
+
def test_start_new_thread(self):
import thread
feedback = []
@@ -141,3 +165,25 @@
self.waitfor(lambda: done, delay=3)
assert done # see stderr for failures in threads
assert sorted(lst) == range(120)
+
+ def test_many_threads(self):
+ import thread, time
+ if self.can_start_many_threads:
+ skip("this OS supports too many threads to check (> 1000)")
+ lock = thread.allocate_lock()
+ lock.acquire()
+ def f():
+ lock.acquire()
+ lock.release()
+ try:
+ try:
+ for i in range(1000):
+ thread.start_new_thread(f, ())
+ finally:
+ lock.release()
+ # wait a bit to allow most threads to finish now
+ self.busywait(2.0)
+ except (thread.error, MemoryError):
+ pass
+ else:
+ raise Exception("could unexpectedly start 1000 threads")
More information about the Pypy-commit
mailing list