summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZac Medico2012-09-26 02:25:49 (GMT)
committerZac Medico2012-09-26 02:25:49 (GMT)
commit2b2580d9dac62aa720e5d996fa5102ee5caeffe7 (patch)
treed71e437f6ccb82181cfc81e776031a62744e1655
parentf7648d050e9f3936ff2bc278f6927aa0b901be50 (diff)
EventLoop: fix busy loop waiting for child pid
This fixes a case where EventLoop could consume 100% CPU while waiting for a child process. It also fixes timeout calculations in python 2.x, where it was using integer division instead of float.
-rw-r--r--pym/portage/util/_eventloop/EventLoop.py30
-rw-r--r--pym/portage/util/_eventloop/PollSelectAdapter.py2
2 files changed, 18 insertions, 14 deletions
diff --git a/pym/portage/util/_eventloop/EventLoop.py b/pym/portage/util/_eventloop/EventLoop.py
index 44a3c26..15d4ef2 100644
--- a/pym/portage/util/_eventloop/EventLoop.py
+++ b/pym/portage/util/_eventloop/EventLoop.py
@@ -137,15 +137,15 @@ class EventLoop(object):
if not event_handlers:
if self._run_timeouts():
events_handled += 1
- if not event_handlers:
- if not events_handled and may_block and \
- self._timeout_interval is not None:
+ if not event_handlers and not events_handled and may_block:
+ timeout = self._get_poll_timeout()
+ if timeout is not None:
# Block so that we don't waste cpu time by looping too
# quickly. This makes EventLoop useful for code that needs
# to wait for timeout callbacks regardless of whether or
# not any IO handlers are currently registered.
try:
- self._poll(timeout=self._timeout_interval)
+ self._poll(timeout=timeout)
except StopIteration:
pass
if self._run_timeouts():
@@ -160,14 +160,7 @@ class EventLoop(object):
if not event_queue:
if may_block:
- if self._child_handlers:
- if self._timeout_interval is None:
- timeout = self._sigchld_interval
- else:
- timeout = min(self._sigchld_interval,
- self._timeout_interval)
- else:
- timeout = self._timeout_interval
+ timeout = self._get_poll_timeout()
else:
timeout = 0
@@ -194,6 +187,17 @@ class EventLoop(object):
return bool(events_handled)
+ def _get_poll_timeout(self):
+ if self._child_handlers:
+ if self._timeout_interval is None:
+ timeout = self._sigchld_interval
+ else:
+ timeout = min(self._sigchld_interval,
+ self._timeout_interval)
+ else:
+ timeout = self._timeout_interval
+ return timeout
+
def child_watch_add(self, pid, callback, data=None):
"""
Like glib.child_watch_add(), sets callback to be called with the
@@ -532,6 +536,6 @@ class _epoll_adapter(object):
if timeout is None or timeout < 0:
timeout = -1
elif timeout != 0:
- timeout = timeout / 1000
+ timeout = float(timeout) / 1000
return self._epoll_obj.poll(timeout)
diff --git a/pym/portage/util/_eventloop/PollSelectAdapter.py b/pym/portage/util/_eventloop/PollSelectAdapter.py
index 17e63d9..244788c 100644
--- a/pym/portage/util/_eventloop/PollSelectAdapter.py
+++ b/pym/portage/util/_eventloop/PollSelectAdapter.py
@@ -64,7 +64,7 @@ class PollSelectAdapter(object):
if timeout is not None and timeout < 0:
timeout = None
if timeout is not None:
- select_args.append(timeout / 1000)
+ select_args.append(float(timeout) / 1000)
select_events = select.select(*select_args)
poll_events = []