From d93059ac7e65fb71c6d18254c175731176781920 Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 9 Apr 2009 06:16:03 +0000 Subject: Bug #264435 - Handle EAGAIN errors when writing to stdout, due to poorly behaved subprocesses that set O_NONBLOCK mode on inherited file descriptors. TODO: When possible, avoid having child processes inherit stdio file descriptors from portage (maybe it can't be avoided with PROPERTIES=interactive). svn path=/main/trunk/; revision=13306 --- pym/_emerge/__init__.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) (limited to 'pym/_emerge/__init__.py') diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py index 6b526564a..fc7b3e6ad 100644 --- a/pym/_emerge/__init__.py +++ b/pym/_emerge/__init__.py @@ -2426,8 +2426,41 @@ class SpawnProcess(SubProcess): if buf: if not self.background: - buf.tofile(files.stdout) - files.stdout.flush() + write_successful = False + failures = 0 + while True: + try: + if not write_successful: + buf.tofile(files.stdout) + write_successful = True + files.stdout.flush() + break + except IOError, e: + if e.errno != errno.EAGAIN: + raise + del e + failures += 1 + if failures > 50: + # Avoid a potentially infinite loop. In + # most cases, the failure count is zero + # and it's unlikely to exceed 1. + raise + + # This means that a subprocess has put an inherited + # stdio file descriptor (typically stdin) into + # O_NONBLOCK mode. This is not acceptable (see bug + # #264435), so revert it. We need to use a loop + # here since there's a race condition due to + # parallel processes being able to change the + # flags on the inherited file descriptor. + # TODO: When possible, avoid having child processes + # inherit stdio file descriptors from portage + # (maybe it can't be avoided with + # PROPERTIES=interactive). + fcntl.fcntl(files.stdout.fileno(), fcntl.F_SETFL, + fcntl.fcntl(files.stdout.fileno(), + fcntl.F_GETFL) ^ os.O_NONBLOCK) + buf.tofile(files.log) files.log.flush() else: -- cgit v1.2.3-1-g7c22