Commit 0774d4c1 authored by Jason Madden's avatar Jason Madden

libev follows libuv by not updating the loop time in a timer by default. A...

libev follows libuv by not updating the loop time in a timer by default. A Timeout that we use internally still does this though.
parent f1db162c
......@@ -190,18 +190,19 @@ libuv
happen in a different order, and timers may easily be off by up to
half of the supposed 1ms resolution. See :issue:`1057`.
- Starting timers does not update the loop's time by default. This
is because, unlike libev, a timer callback can cause other timer
callbacks to be run if they expire because the loop's time
updated, without cycling the event loop. See :issue:`1057`.
- Starting a ``timer`` watcher does not update the loop's time by
default. This is because, unlike libev, a timer callback can cause
other timer callbacks to be run if they expire because the loop's
time updated, without cycling the event loop. See :issue:`1057`.
.. note:: libev might be changed to follow this behaviour.
libev has also been changed to follow this behaviour.
Again, this is extremely experimental and all of it is subject to
change.
See :issue:`790` for history and more in-depth discussion.
1.2.2 (2017-06-05)
==================
......
......@@ -423,7 +423,7 @@ class IoMixin(object):
class TimerMixin(object):
_watcher_type = 'timer'
update_loop_time_on_start = True
update_loop_time_on_start = False
def __init__(self, loop, after=0.0, repeat=0.0, ref=True, priority=None):
if repeat < 0.0:
......@@ -441,7 +441,8 @@ class TimerMixin(object):
# runs for a very long time without entering the event
# loop, updating libev's idea of the current time is a
# good idea."
# So do we really need to default to true?
# 1.3 changed the default for this to False. Note that
# starting Timeout objects internally still sets this to true.
self._update_now()
super(TimerMixin, self).start(callback, *args)
......
......@@ -893,13 +893,17 @@ cdef public class timer(watcher) [object PyGeventTimerObject, type PyGeventTimer
WATCHER_BASE(timer)
def start(self, object callback, *args, update=True):
update_loop_time_on_start = False
def start(self, object callback, *args, update=None):
CHECK_LOOP2(self.loop)
if callback is None:
raise TypeError('callback must be callable, not None')
self.callback = callback
self.args = args
LIBEV_UNREF
if update is None:
update = self.update_loop_time_on_start
if update:
libev.ev_now_update(self.loop._ptr)
libev.ev_timer_start(self.loop._ptr, &self._watcher)
......
......@@ -191,6 +191,7 @@ class Timeout(BaseException):
return _FakeTimer
# If we don't update the time here (and the timer watcher doesn't),
# as under libuv, then certain tests hang, notably the monkey-patched test_telnetlib
# in test_read_eager_A. libev does not demonstrate this behaviour.
return Timeout.start_new(timeout, exception, _update=True)
@property
......
......@@ -64,9 +64,8 @@ try:
except ImportError:
pass
if greentest.PYPY or PY3:
from errno import ECONNRESET
CONN_ABORTED_ERRORS.append(ECONNRESET)
from errno import ECONNRESET
CONN_ABORTED_ERRORS.append(ECONNRESET)
REASONS = {200: 'OK',
500: 'Internal Server Error'}
......@@ -92,7 +91,7 @@ def read_headers(fd):
except:
print('Failed to split: %r' % (line, ))
raise
assert key.lower() not in [x.lower() for x in headers.keys()], 'Header %r:%r sent more than once: %r' % (key, value, headers)
assert key.lower() not in {x.lower() for x in headers}, 'Header %r:%r sent more than once: %r' % (key, value, headers)
headers[key] = value
return response_line, headers
......@@ -375,12 +374,17 @@ class CommonTests(TestCase):
fd.write('GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n')
read_http(fd)
fd.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
# This may either raise, or it may return an empty response,
# depend on timing and the Python version.
try:
result = fd.readline()
assert not result, 'The remote side is expected to close the connection, but it send %r' % (result, )
except socket.error as ex:
if ex.args[0] not in CONN_ABORTED_ERRORS:
raise
else:
self.assertFalse(
result,
'The remote side is expected to close the connection, but it sent %r' % (result,))
def SKIP_test_006_reject_long_urls(self):
fd = self.makefile()
......@@ -1413,16 +1417,16 @@ class Handler(pywsgi.WSGIHandler):
def read_requestline(self):
data = self.rfile.read(7)
if data[0] == b'<'[0]:
try:
data += self.rfile.read(15)
if data.lower() == b'<policy-file-request/>':
self.socket.sendall(b'HELLO')
else:
self.log_error('Invalid request: %r', data)
finally:
self.socket.shutdown(socket.SHUT_WR)
self.socket.close()
self.socket = None
# Returning nothing stops handle_one_request()
# Note that closing or even deleting self.socket() here
# can lead to the read side throwing Connection Reset By Peer,
# depending on the Python version and OS
data += self.rfile.read(15)
if data.lower() == b'<policy-file-request/>':
self.socket.sendall(b'HELLO')
else:
self.log_error('Invalid request: %r', data)
return None
else:
return data + self.rfile.readline()
......@@ -1452,6 +1456,7 @@ class TestHandlerSubclass(TestCase):
read_http(fd)
fd = self.makefile()
# Trigger an error
fd.write('<policy-file-XXXuest/>\x00')
fd.flush()
self.assertEqual(fd.read(), b'')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment