summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2012-02-11 21:36:18 -0800
committerZac Medico <zmedico@gentoo.org>2012-02-11 21:36:18 -0800
commitc36768027d04f10f7af4402f642e93144d1b353b (patch)
tree40a3452e58af72246e6d8b457e76dd60c27fa224
parentfc42d39d0ac9043b7a480d914b12fa679e4e2785 (diff)
downloadportage-c36768027d04f10f7af4402f642e93144d1b353b.tar.gz
portage-c36768027d04f10f7af4402f642e93144d1b353b.tar.bz2
portage-c36768027d04f10f7af4402f642e93144d1b353b.zip
EbuildIpcDaemon: handle POLLHUP, bug #401919
-rw-r--r--pym/_emerge/EbuildIpcDaemon.py24
1 files changed, 24 insertions, 0 deletions
diff --git a/pym/_emerge/EbuildIpcDaemon.py b/pym/_emerge/EbuildIpcDaemon.py
index 5795bfbdc..8414d2020 100644
--- a/pym/_emerge/EbuildIpcDaemon.py
+++ b/pym/_emerge/EbuildIpcDaemon.py
@@ -5,7 +5,9 @@ import errno
import logging
import pickle
from portage import os
+from portage.exception import TryAgain
from portage.localization import _
+from portage.locks import lockfile, unlockfile
from portage.util import writemsg_level
from _emerge.FifoIpcDaemon import FifoIpcDaemon
@@ -83,6 +85,28 @@ class EbuildIpcDaemon(FifoIpcDaemon):
if reply_hook is not None:
reply_hook()
+ elif event & self.scheduler.IO_HUP:
+ # This can be triggered due to a race condition which happens when
+ # the previous _reopen_input() call occurs before the writer has
+ # closed the pipe (see bug #401919). It's not safe to re-open
+ # without a lock here, since it's possible that another writer will
+ # write something to the pipe just before we close it, and in that
+ # case the write will be lost. Therefore, try for a non-blocking
+ # lock, and only re-open the pipe if the lock is acquired.
+ lock_filename = os.path.join(
+ os.path.dirname(self.input_fifo), '.ipc_lock')
+ try:
+ lock_obj = lockfile(lock_filename, unlinkfile=True,
+ flags=os.O_NONBLOCK)
+ except TryAgain:
+ # We'll try again when another IO_HUP event arrives.
+ pass
+ else:
+ try:
+ self._reopen_input()
+ finally:
+ unlockfile(lock_obj)
+
return True
def _send_reply(self, reply):