diff options
author | Zac Medico <zmedico@gentoo.org> | 2011-03-17 14:39:53 -0700 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2011-03-18 12:50:22 -0700 |
commit | 2f3235abef72d61cdcdf549a08e645933698a4ff (patch) | |
tree | 7bf380e73a7d7835d175cb364bdb60d9b86c6c1b /pym | |
parent | 768958c9d1504f72d2f252c1793a5bc48a2a4a85 (diff) | |
download | portage-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.py | 29 |
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) |