Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r13306 - main/trunk/pym/_emerge
Date: Thu, 09 Apr 2009 06:16:07
Message-Id: E1LrnYS-00058B-5F@stork.gentoo.org
1 Author: zmedico
2 Date: 2009-04-09 06:16:03 +0000 (Thu, 09 Apr 2009)
3 New Revision: 13306
4
5 Modified:
6 main/trunk/pym/_emerge/__init__.py
7 Log:
8 Bug #264435 - Handle EAGAIN errors when writing to stdout, due to poorly
9 behaved subprocesses that set O_NONBLOCK mode on inherited file descriptors.
10 TODO: When possible, avoid having child processes inherit stdio file
11 descriptors from portage (maybe it can't be avoided with
12 PROPERTIES=interactive).
13
14
15 Modified: main/trunk/pym/_emerge/__init__.py
16 ===================================================================
17 --- main/trunk/pym/_emerge/__init__.py 2009-04-08 20:48:08 UTC (rev 13305)
18 +++ main/trunk/pym/_emerge/__init__.py 2009-04-09 06:16:03 UTC (rev 13306)
19 @@ -2426,8 +2426,41 @@
20
21 if buf:
22 if not self.background:
23 - buf.tofile(files.stdout)
24 - files.stdout.flush()
25 + write_successful = False
26 + failures = 0
27 + while True:
28 + try:
29 + if not write_successful:
30 + buf.tofile(files.stdout)
31 + write_successful = True
32 + files.stdout.flush()
33 + break
34 + except IOError, e:
35 + if e.errno != errno.EAGAIN:
36 + raise
37 + del e
38 + failures += 1
39 + if failures > 50:
40 + # Avoid a potentially infinite loop. In
41 + # most cases, the failure count is zero
42 + # and it's unlikely to exceed 1.
43 + raise
44 +
45 + # This means that a subprocess has put an inherited
46 + # stdio file descriptor (typically stdin) into
47 + # O_NONBLOCK mode. This is not acceptable (see bug
48 + # #264435), so revert it. We need to use a loop
49 + # here since there's a race condition due to
50 + # parallel processes being able to change the
51 + # flags on the inherited file descriptor.
52 + # TODO: When possible, avoid having child processes
53 + # inherit stdio file descriptors from portage
54 + # (maybe it can't be avoided with
55 + # PROPERTIES=interactive).
56 + fcntl.fcntl(files.stdout.fileno(), fcntl.F_SETFL,
57 + fcntl.fcntl(files.stdout.fileno(),
58 + fcntl.F_GETFL) ^ os.O_NONBLOCK)
59 +
60 buf.tofile(files.log)
61 files.log.flush()
62 else: