From: Zac Medico Date: Sun, 13 Jul 2008 13:24:39 +0000 (-0000) Subject: * Since can_poll_pty() is unsafe due to he possibility of the poll() call X-Git-Tag: v2.2_rc2~108 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=2cba51ec393227e8d2038aa84194162ed89c23ef;p=portage.git * Since can_poll_pty() is unsafe due to he possibility of 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(). svn path=/main/trunk/; revision=11039 --- diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 12cd9c690..e03b57072 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -7974,57 +7974,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(): """ @@ -8032,7 +8017,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() 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)