From: Fabian Groffen Date: Sun, 13 Jul 2008 14:28:38 +0000 (-0000) Subject: Merged from trunk 11038:11040 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=e1dc59f5d3d2cfa8c8bb40eb1330f2e4206618d1;p=portage.git Merged from trunk 11038:11040 | 11039 | * Since can_poll_pty() is unsafe due to he possibility of | | zmedico | the poll() call blocking forever, replace it with a simpler | | | test on /dev/null that's derived from a test in a glib2 | | | configure script. * Remove PtyReaderTestCase since it has | | | the same problem as can_poll_pty(). | | 11040 | Remove all traces of the "poll" parameter for the | | zmedico | PollScheduler constructor since it was only used by | | | can_poll_pty(). | svn path=/main/branches/prefix/; revision=11041 --- diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index a67fd5edf..3d4296fa3 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -8015,57 +8015,42 @@ class SequentialTaskQueue(SlotObject): def __len__(self): return len(self._task_queue) + len(self.running_tasks) -_can_poll_pty = None +_can_poll_device = None -def can_poll_pty(): +def can_poll_device(): """ - Test if it's possible to use poll() on a pty device. This + Test if it's possible to use poll() on a device such as a pty. This is known to fail on Darwin. @rtype: bool - @returns: True if poll() on a pty device succeeds, False otherwise. + @returns: True if poll() on a device succeeds, False otherwise. """ - global _can_poll_pty - if _can_poll_pty is not None: - return _can_poll_pty + global _can_poll_device + if _can_poll_device is not None: + return _can_poll_device if not hasattr(select, "poll"): - _can_poll_pty = False - return _can_poll_pty + _can_poll_device = False + return _can_poll_device - got_pty, master_fd, slave_fd = \ - portage._create_pty_or_pipe(copy_term_size=sys.stdout.fileno()) - if not got_pty: - os.close(master_fd) - os.close(slave_fd) - _can_poll_pty = False - return _can_poll_pty - - test_string = 2 * "blah blah blah\n" - - master_file = os.fdopen(master_fd, 'r') - - task_scheduler = TaskScheduler(max_jobs=2, poll=select.poll()) - scheduler = task_scheduler.sched_iface - - producer = SpawnProcess( - args=["bash", "-c", "echo -n '%s'" % test_string], - fd_pipes={1:slave_fd,2:slave_fd}, scheduler=scheduler) - - consumer = PipeReader( - input_files={"producer" : master_file}, - scheduler=scheduler) - - task_scheduler.add(producer) - task_scheduler.add(consumer) - - def producer_start_cb(task): - os.close(slave_fd) + try: + dev_null = open('/dev/null', 'rb') + except IOError: + _can_poll_device = False + return _can_poll_device + + p = select.poll() + p.register(dev_null.fileno(), PollConstants.POLLIN) + + invalid_request = False + for f, event in p.poll(): + if event & PollConstants.POLLNVAL: + invalid_request = True + break + dev_null.close() - producer.addStartListener(producer_start_cb) - task_scheduler.run() - _can_poll_pty = test_string == consumer.getvalue() - return _can_poll_pty + _can_poll_device = not invalid_request + return _can_poll_device def create_poll_instance(): """ @@ -8073,7 +8058,7 @@ def create_poll_instance(): PollSelectAdapter there is no poll() implementation or it is broken somehow. """ - if can_poll_pty(): + if can_poll_device(): return select.poll() return PollSelectAdapter() @@ -8082,7 +8067,7 @@ class PollScheduler(object): class _sched_iface_class(SlotObject): __slots__ = ("register", "schedule", "unregister") - def __init__(self, poll=None): + def __init__(self): self._max_jobs = 1 self._max_load = None self._jobs = 0 @@ -8090,9 +8075,7 @@ class PollScheduler(object): self._poll_event_handler_ids = {} # Increment id for each new handler. self._event_handler_id = 0 - if poll is None: - poll = create_poll_instance() - self._poll = poll + self._poll = create_poll_instance() self._scheduling = False def _schedule(self): @@ -8197,8 +8180,8 @@ class QueueScheduler(PollScheduler): run() method returns when no tasks remain. """ - def __init__(self, max_jobs=None, max_load=None, poll=None): - PollScheduler.__init__(self, poll=poll) + def __init__(self, max_jobs=None, max_load=None): + PollScheduler.__init__(self) if max_jobs is None: max_jobs = 1 @@ -8272,10 +8255,10 @@ class TaskScheduler(object): add tasks and call run(). The run() method returns when no tasks remain. """ - def __init__(self, max_jobs=None, max_load=None, poll=None): + def __init__(self, max_jobs=None, max_load=None): self._queue = SequentialTaskQueue(max_jobs=max_jobs) self._scheduler = QueueScheduler( - max_jobs=max_jobs, max_load=max_load, poll=poll) + max_jobs=max_jobs, max_load=max_load) self.sched_iface = self._scheduler.sched_iface self.run = self._scheduler.run self._scheduler.add(self._queue) diff --git a/pym/portage/tests/process/test_poll.py b/pym/portage/tests/process/test_poll.py index 8a52f4577..96749d567 100644 --- a/pym/portage/tests/process/test_poll.py +++ b/pym/portage/tests/process/test_poll.py @@ -51,19 +51,3 @@ class PipeReaderTestCase(TestCase): task_scheduler.run() self._assertEqual(test_string, consumer.getvalue()) - -class PtyReaderTestCase(PipeReaderTestCase): - - def _assertEqual(self, test_string, consumer_value): - if test_string != consumer_value: - # This test is expected to fail on some operating systems - # such as Darwin that do not support poll() on pty devices. - self.todo = True - self.assertEqual(test_string, consumer_value) - - def _create_pipe(self): - - got_pty, master_fd, slave_fd = \ - portage._create_pty_or_pipe(copy_term_size=sys.stdout.fileno()) - - return (master_fd, slave_fd)