
This includes: * patching more tests to pass * removing few unit tests which I think are redundant * repeating SSL socket reads in a loop to read all data (I suspect this is related to the fact that writelines is used in the server code there and Python 3 writelines calls write/send repeatedly while on Python 2 it calls it once; on one hand there's no guarantee that single recv/read will return all data sent by the server, on the other hand it's quite suspicious that the number of required reads seems to be connected to the number of sends on the other side of the connection) * working through Python 2/Python 3 threading and thread differences; the lock code I used is the simplest way I could make the tests pass but will likely need to be modified in order to match the original This commit includes 6bcb1dc and closes GH #153
90 lines
2.1 KiB
Python
90 lines
2.1 KiB
Python
"""Implements the standard thread module, using greenthreads."""
|
|
from eventlet.support.six.moves import _thread as __thread
|
|
from eventlet.support import greenlets as greenlet, six
|
|
from eventlet import greenthread
|
|
from eventlet.semaphore import Semaphore as LockType
|
|
|
|
|
|
__patched__ = ['get_ident', 'start_new_thread', 'start_new', 'allocate_lock',
|
|
'allocate', 'exit', 'interrupt_main', 'stack_size', '_local',
|
|
'LockType', '_count']
|
|
|
|
error = __thread.error
|
|
__threadcount = 0
|
|
|
|
|
|
if six.PY3:
|
|
def _set_sentinel():
|
|
# TODO this is a dummy code, reimplementing this may be needed:
|
|
# https://hg.python.org/cpython/file/b5e9bc4352e1/Modules/_threadmodule.c#l1203
|
|
return allocate_lock()
|
|
|
|
TIMEOUT_MAX = __thread.TIMEOUT_MAX
|
|
|
|
|
|
def _count():
|
|
return __threadcount
|
|
|
|
|
|
def get_ident(gr=None):
|
|
if gr is None:
|
|
return id(greenlet.getcurrent())
|
|
else:
|
|
return id(gr)
|
|
|
|
|
|
def __thread_body(func, args, kwargs):
|
|
global __threadcount
|
|
__threadcount += 1
|
|
try:
|
|
func(*args, **kwargs)
|
|
finally:
|
|
__threadcount -= 1
|
|
|
|
|
|
def start_new_thread(function, args=(), kwargs=None):
|
|
kwargs = kwargs or {}
|
|
g = greenthread.spawn_n(__thread_body, function, args, kwargs)
|
|
return get_ident(g)
|
|
|
|
|
|
start_new = start_new_thread
|
|
|
|
|
|
def allocate_lock(*a):
|
|
return LockType(1)
|
|
|
|
|
|
allocate = allocate_lock
|
|
|
|
|
|
def exit():
|
|
raise greenlet.GreenletExit
|
|
|
|
|
|
exit_thread = __thread.exit_thread
|
|
|
|
|
|
def interrupt_main():
|
|
curr = greenlet.getcurrent()
|
|
if curr.parent and not curr.parent.dead:
|
|
curr.parent.throw(KeyboardInterrupt())
|
|
else:
|
|
raise KeyboardInterrupt()
|
|
|
|
|
|
if hasattr(__thread, 'stack_size'):
|
|
__original_stack_size__ = __thread.stack_size
|
|
|
|
def stack_size(size=None):
|
|
if size is None:
|
|
return __original_stack_size__()
|
|
if size > __original_stack_size__():
|
|
return __original_stack_size__(size)
|
|
else:
|
|
pass
|
|
# not going to decrease stack_size, because otherwise other greenlets in
|
|
# this thread will suffer
|
|
|
|
from eventlet.corolocal import local as _local
|