Bug #336644 - Make ebuild-ipc.py use array.fromfile() to read pickles
authorZac Medico <zmedico@gentoo.org>
Fri, 10 Sep 2010 04:51:37 +0000 (21:51 -0700)
committerZac Medico <zmedico@gentoo.org>
Fri, 10 Sep 2010 04:51:37 +0000 (21:51 -0700)
in single atomic non-blocking read() calls, similar to how
AbstractPollTask._read_buf() does it. If the read fails, exit with
status 2 so that best_version() and has_version() can detect the
error and die when necessary.

bin/ebuild-ipc.py
bin/ebuild.sh

index 13c0626541ed3f5479d918794461dda11490b4ae..3869a3c49b44f1fbfa89a9eed3ad4ed8e040f28e 100755 (executable)
@@ -5,6 +5,7 @@
 # This is a helper which ebuild processes can use
 # to communicate with portage's main python process.
 
+import array
 import logging
 import os
 import pickle
@@ -34,6 +35,7 @@ portage._disable_legacy_globals()
 class EbuildIpc(object):
 
        _COMMUNICATE_TIMEOUT_SECONDS = 40
+       _BUFSIZE = 4096
 
        def __init__(self):
                self.fifo_dir = os.environ['PORTAGE_BUILDDIR']
@@ -82,31 +84,33 @@ class EbuildIpc(object):
 
                events = select.select([input_file], [], [])
 
-               # Read the whole pickle in a single read() call since
-               # this stream is in non-blocking mode and pickle.load()
-               # has been known to raise the following exception when
-               # reading from a non-blocking stream:
-               #
-               #   File "/usr/lib64/python2.6/pickle.py", line 1370, in load
-               #     return Unpickler(file).load()
-               #   File "/usr/lib64/python2.6/pickle.py", line 858, in load
-               #     dispatch[key](self)
-               #   File "/usr/lib64/python2.6/pickle.py", line 1195, in load_setitem
-               #     value = stack.pop()
-               # IndexError: pop from empty list
-
-               pickle_str = input_file.read()
-               reply = pickle.loads(pickle_str)
-               output_file.close()
-               input_file.close()
-
-               (out, err, rval) = reply
-
-               if out:
-                       portage.util.writemsg_stdout(out, noiselevel=-1)
-
-               if err:
-                       portage.util.writemsg(err, noiselevel=-1)
+               # Read the whole pickle in a single atomic read() call.
+               buf = array.array('B')
+               try:
+                       buf.fromfile(input_file, self._BUFSIZE)
+               except EOFError as e:
+                       #portage.util.writemsg("%s\n" % (e), noiselevel=-1)
+                       pass
+               except IOError as e:
+                       portage.util.writemsg("%s\n" % (e), noiselevel=-1)
+
+               if buf:
+
+                       reply = pickle.loads(buf.tostring())
+                       output_file.close()
+                       input_file.close()
+
+                       (out, err, rval) = reply
+
+                       if out:
+                               portage.util.writemsg_stdout(out, noiselevel=-1)
+
+                       if err:
+                               portage.util.writemsg(err, noiselevel=-1)
+
+               else:
+
+                       rval = 2
 
                return rval
 
index cc3b4a1424b74e4c07a4ad4f7fa7bc70db35f420..a742eae62fa107af3e678e4d733feffd217e4070 100755 (executable)
@@ -180,13 +180,13 @@ has_version() {
                die "portageq calls (has_version calls portageq) are not allowed in the global scope"
        fi
 
+       local retval
        if [[ -n $PORTAGE_IPC_DAEMON ]] ; then
                "$PORTAGE_BIN_PATH"/ebuild-ipc has_version "$ROOT" "$1"
-               return $?
+       else
+               PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \
+               "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" has_version "${ROOT}" "$1"
        fi
-
-       PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \
-       "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" has_version "${ROOT}" "$1"
        local retval=$?
        case "${retval}" in
                0)
@@ -225,11 +225,10 @@ best_version() {
 
        if [[ -n $PORTAGE_IPC_DAEMON ]] ; then
                "$PORTAGE_BIN_PATH"/ebuild-ipc best_version "$ROOT" "$1"
-               return $?
+       else
+               PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \
+               "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" 'best_version' "${ROOT}" "$1"
        fi
-
-       PYTHONPATH=${PORTAGE_PYM_PATH}${PYTHONPATH:+:}${PYTHONPATH} \
-       "${PORTAGE_PYTHON:-/usr/bin/python}" "${PORTAGE_BIN_PATH}/portageq" 'best_version' "${ROOT}" "$1"
        local retval=$?
        case "${retval}" in
                0)