summaryrefslogtreecommitdiffstats
path: root/pym
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2011-03-17 14:39:53 -0700
committerZac Medico <zmedico@gentoo.org>2011-03-18 12:50:22 -0700
commit2f3235abef72d61cdcdf549a08e645933698a4ff (patch)
tree7bf380e73a7d7835d175cb364bdb60d9b86c6c1b /pym
parent768958c9d1504f72d2f252c1793a5bc48a2a4a85 (diff)
downloadportage-2f3235abef72d61cdcdf549a08e645933698a4ff.tar.gz
portage-2f3235abef72d61cdcdf549a08e645933698a4ff.tar.bz2
portage-2f3235abef72d61cdcdf549a08e645933698a4ff.zip
EbuildIpcDaemon: use non-blocking write
This prevents the Scheduler from hanging if the client is killed before we can send the reply, as reported by David James: http://codereview.chromium.org/6713003 This commit depends on ebuild-ipc (the client) opening the other side of this fifo before it sends its request, which has already been added in commit eff879ff0ce7dcc1ce68d5f16de1ec73051f8c18.
Diffstat (limited to 'pym')
-rw-r--r--pym/_emerge/EbuildIpcDaemon.py29
1 files changed, 24 insertions, 5 deletions
diff --git a/pym/_emerge/EbuildIpcDaemon.py b/pym/_emerge/EbuildIpcDaemon.py
index efcda9316..5dabe34b3 100644
--- a/pym/_emerge/EbuildIpcDaemon.py
+++ b/pym/_emerge/EbuildIpcDaemon.py
@@ -1,9 +1,12 @@
-# Copyright 2010 Gentoo Foundation
+# Copyright 2010-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
import errno
+import logging
import pickle
from portage import os
+from portage.localization import _
+from portage.util import writemsg_level
from _emerge.FifoIpcDaemon import FifoIpcDaemon
from _emerge.PollConstants import PollConstants
@@ -83,7 +86,23 @@ class EbuildIpcDaemon(FifoIpcDaemon):
def _send_reply(self, reply):
# File streams are in unbuffered mode since we do atomic
- # read and write of whole pickles.
- output_file = open(self.output_fifo, 'wb', 0)
- output_file.write(pickle.dumps(reply))
- output_file.close()
+ # read and write of whole pickles. Use non-blocking mode so
+ # we don't hang if the client is killed before we can send
+ # the reply. We rely on the client opening the other side
+ # of this fifo before it sends its request, since otherwise
+ # we'd have a race condition with this open call raising
+ # ENXIO if the client hasn't opened the fifo yet.
+ try:
+ output_fd = os.open(self.output_fifo,
+ os.O_WRONLY | os.O_NONBLOCK)
+ try:
+ os.write(output_fd, pickle.dumps(reply))
+ finally:
+ os.close(output_fd)
+ except OSError as e:
+ # This probably means that the client has been killed,
+ # which causes open to fail with ENXIO.
+ writemsg_level(
+ "!!! EbuildIpcDaemon %s: %s\n" % \
+ (_('failed to send reply'), e),
+ level=logging.ERROR, noiselevel=-1)