Package _emerge :: Module AbstractPollTask
[hide private]

Source Code for Module _emerge.AbstractPollTask

  1  # Copyright 1999-2012 Gentoo Foundation 
  2  # Distributed under the terms of the GNU General Public License v2 
  3   
  4  import array 
  5  import errno 
  6  import logging 
  7  import os 
  8   
  9  from portage.util import writemsg_level 
 10  from _emerge.AsynchronousTask import AsynchronousTask 
11 12 -class AbstractPollTask(AsynchronousTask):
13 14 __slots__ = ("scheduler",) + \ 15 ("_registered",) 16 17 _bufsize = 4096 18 19 @property
20 - def _exceptional_events(self):
21 return self.scheduler.IO_ERR | self.scheduler.IO_NVAL
22 23 @property
24 - def _registered_events(self):
25 return self.scheduler.IO_IN | self.scheduler.IO_HUP | \ 26 self._exceptional_events
27
28 - def isAlive(self):
29 return bool(self._registered)
30
31 - def _read_array(self, f, event):
32 """ 33 NOTE: array.fromfile() is used here only for testing purposes, 34 because it has bugs in all known versions of Python (including 35 Python 2.7 and Python 3.2). See PipeReaderArrayTestCase. 36 37 | POLLIN | RETURN 38 | BIT | VALUE 39 | --------------------------------------------------- 40 | 1 | Read self._bufsize into an instance of 41 | | array.array('B') and return it, handling 42 | | EOFError and IOError. An empty array 43 | | indicates EOF. 44 | --------------------------------------------------- 45 | 0 | None 46 """ 47 buf = None 48 if event & self.scheduler.IO_IN: 49 buf = array.array('B') 50 try: 51 buf.fromfile(f, self._bufsize) 52 except EOFError: 53 pass 54 except TypeError: 55 # Python 3.2: 56 # TypeError: read() didn't return bytes 57 pass 58 except IOError as e: 59 # EIO happens with pty on Linux after the 60 # slave end of the pty has been closed. 61 if e.errno == errno.EIO: 62 # EOF: return empty string of bytes 63 pass 64 elif e.errno == errno.EAGAIN: 65 # EAGAIN: return None 66 buf = None 67 else: 68 raise 69 70 if buf is not None: 71 try: 72 # Python >=3.2 73 buf = buf.tobytes() 74 except AttributeError: 75 buf = buf.tostring() 76 77 return buf
78
79 - def _read_buf(self, fd, event):
80 """ 81 | POLLIN | RETURN 82 | BIT | VALUE 83 | --------------------------------------------------- 84 | 1 | Read self._bufsize into a string of bytes, 85 | | handling EAGAIN and EIO. An empty string 86 | | of bytes indicates EOF. 87 | --------------------------------------------------- 88 | 0 | None 89 """ 90 # NOTE: array.fromfile() is no longer used here because it has 91 # bugs in all known versions of Python (including Python 2.7 92 # and Python 3.2). 93 buf = None 94 if event & self.scheduler.IO_IN: 95 try: 96 buf = os.read(fd, self._bufsize) 97 except OSError as e: 98 # EIO happens with pty on Linux after the 99 # slave end of the pty has been closed. 100 if e.errno == errno.EIO: 101 # EOF: return empty string of bytes 102 buf = b'' 103 elif e.errno == errno.EAGAIN: 104 # EAGAIN: return None 105 buf = None 106 else: 107 raise 108 109 return buf
110
111 - def _unregister(self):
112 raise NotImplementedError(self)
113
114 - def _log_poll_exception(self, event):
115 writemsg_level( 116 "!!! %s received strange poll event: %s\n" % \ 117 (self.__class__.__name__, event,), 118 level=logging.ERROR, noiselevel=-1)
119
120 - def _unregister_if_appropriate(self, event):
121 if self._registered: 122 if event & self._exceptional_events: 123 self._log_poll_exception(event) 124 self._unregister() 125 self.cancel() 126 self.wait() 127 elif event & self.scheduler.IO_HUP: 128 self._unregister() 129 self.wait()
130
131 - def _wait(self):
132 if self.returncode is not None: 133 return self.returncode 134 self._wait_loop() 135 return self.returncode
136
137 - def _wait_loop(self, timeout=None):
138 139 if timeout is None: 140 while self._registered: 141 self.scheduler.iteration() 142 return 143 144 def timeout_cb(): 145 timeout_cb.timed_out = True 146 return False
147 timeout_cb.timed_out = False 148 timeout_cb.timeout_id = self.scheduler.timeout_add(timeout, timeout_cb) 149 150 try: 151 while self._registered and not timeout_cb.timed_out: 152 self.scheduler.iteration() 153 finally: 154 self.scheduler.source_remove(timeout_cb.timeout_id)
155