diff options
author | Zac Medico <zmedico@gentoo.org> | 2009-04-09 06:16:03 +0000 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2009-04-09 06:16:03 +0000 |
commit | d93059ac7e65fb71c6d18254c175731176781920 (patch) | |
tree | b4fe29c6adb842ed70e7111310f1a9fb4dfe2a7e | |
parent | 43a864ffa96ebaecb98971e74cfeb35a42b9b34d (diff) | |
download | portage-d93059ac7e65fb71c6d18254c175731176781920.tar.gz portage-d93059ac7e65fb71c6d18254c175731176781920.tar.bz2 portage-d93059ac7e65fb71c6d18254c175731176781920.zip |
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
-rw-r--r-- | pym/_emerge/__init__.py | 37 |
1 files changed, 35 insertions, 2 deletions
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: |