From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id 441B51389E2 for ; Fri, 26 Dec 2014 09:01:02 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 25BA3E0AF0; Fri, 26 Dec 2014 09:01:00 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id A8726E0AE9 for ; Fri, 26 Dec 2014 09:00:59 +0000 (UTC) Received: from localhost.localdomain (67-203-132-147.static-ip.telepacific.net [67.203.132.147]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: zmedico) by smtp.gentoo.org (Postfix) with ESMTPSA id 3C367340589; Fri, 26 Dec 2014 09:00:58 +0000 (UTC) From: Zac Medico To: gentoo-portage-dev@lists.gentoo.org Cc: Zac Medico Subject: [gentoo-portage-dev] [PATCH] AbstractPollTask._read_buf: read regardless of event flags (531724) Date: Fri, 26 Dec 2014 01:00:41 -0800 Message-Id: <1419584441-23770-1-git-send-email-zmedico@gentoo.org> X-Mailer: git-send-email 2.0.5 Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-portage-dev@lists.gentoo.org Reply-to: gentoo-portage-dev@lists.gentoo.org X-Archives-Salt: ebfe08c5-eb29-4ab3-ac4c-df94e2248cbc X-Archives-Hash: f0105db435ff6811ae9e650b8163e31d PipeReaderPtyTestCase shows that data may be lost unless we attempt to read data for every poll event, regardless of the event flags. Therefore, always read, regardless of the event flags. This is safe to do because all consumers of this API use non-blocking mode and properly handle EAGAIN (signaled when this method returns None). X-Gentoo-Bug: 531724 X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=531724 --- pym/_emerge/AbstractPollTask.py | 50 +++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/pym/_emerge/AbstractPollTask.py b/pym/_emerge/AbstractPollTask.py index 3f6dd6c..48e7590 100644 --- a/pym/_emerge/AbstractPollTask.py +++ b/pym/_emerge/AbstractPollTask.py @@ -78,33 +78,39 @@ class AbstractPollTask(AsynchronousTask): def _read_buf(self, fd, event): """ - | POLLIN | RETURN - | BIT | VALUE - | --------------------------------------------------- - | 1 | Read self._bufsize into a string of bytes, - | | handling EAGAIN and EIO. An empty string - | | of bytes indicates EOF. - | --------------------------------------------------- - | 0 | None + Read self._bufsize into a string of bytes, handling EAGAIN and + EIO. This will only call os.read() once, so the caller should + call this method in a loop until either None or an empty string + of bytes is returned. An empty string of bytes indicates EOF. + None indicates EAGAIN. + + NOTE: os.read() will be called regardless of the event flags, + since otherwise data may be lost (see bug #531724). + + @param fd: file descriptor (non-blocking mode required) + @type fd: int + @param event: poll event flags + @type event: int + @rtype: bytes or None + @return: A string of bytes, or None """ # NOTE: array.fromfile() is no longer used here because it has # bugs in all known versions of Python (including Python 2.7 # and Python 3.2). buf = None - if event & self.scheduler.IO_IN: - try: - buf = os.read(fd, self._bufsize) - except OSError as e: - # EIO happens with pty on Linux after the - # slave end of the pty has been closed. - if e.errno == errno.EIO: - # EOF: return empty string of bytes - buf = b'' - elif e.errno == errno.EAGAIN: - # EAGAIN: return None - buf = None - else: - raise + try: + buf = os.read(fd, self._bufsize) + except OSError as e: + # EIO happens with pty on Linux after the + # slave end of the pty has been closed. + if e.errno == errno.EIO: + # EOF: return empty string of bytes + buf = b'' + elif e.errno == errno.EAGAIN: + # EAGAIN: return None + buf = None + else: + raise return buf -- 2.0.5