Commit 96ba3338 authored by Ximin Luo's avatar Ximin Luo
Browse files

Tentative fix for #863636, but it sometimes makes the problem worse

This should work in theory and does in practise *except* for the case of
readelf where it works on small cases but fails for large cases and sometimes
makes those cases worse, see the bug report for details.
parent b8bcb462
Loading
Loading
Loading
Loading
+19 −3
Original line number Diff line number Diff line
@@ -192,12 +192,13 @@ def run_diff(fifo1, fifo2, end_nl_q1, end_nl_q2):


class FIFOFeeder(threading.Thread):
    def __init__(self, feeder, fifo_path, end_nl_q=None, daemon=True, *args):
    def __init__(self, feeder, fifo_path, end_nl_q=None, daemon=True, early_eval=False, *args):
        os.mkfifo(fifo_path)
        super().__init__(daemon=daemon)
        self.feeder = feeder
        self.fifo_path = fifo_path
        self.end_nl_q = Queue() if end_nl_q is None else end_nl_q
        self.early_eval = early_eval
        self._exception = None
        self._want_join = threading.Event()

@@ -228,9 +229,24 @@ class FIFOFeeder(threading.Thread):
            fcntl.fcntl(fd, fcntl.F_SETFL, 0)

            with open(fd, 'wb') as fifo:
                # If early-eval is requested, run the feeder and store its output
                # in a temporary file, *before* writing to the "real" fifo. This is
                # necessary to force command-based diffs to run in parallel, see
                # Debian #863636
                feeder = self.feeder
                if self.early_eval:
                    temp_path = self.fifo_path + ".contents"
                    with open(temp_path, 'wb') as temp:
                        end_nl = feeder(temp)
                    def feeder(fifo):
                        with open(temp_path, 'rb') as f:
                            for buf in iter(lambda: f.read(32768), b''):
                                fifo.write(buf)
                        return end_nl

                # The queue works around a unified diff limitation: if there's
                # no newlines in both don't make it a difference
                end_nl = self.feeder(fifo)
                end_nl = feeder(fifo)
                self.end_nl_q.put(end_nl)
        except Exception as error:
            self._exception = error
@@ -248,7 +264,7 @@ def diff(feeder1, feeder2):
    fifo1_path = os.path.join(tmpdir, 'fifo1')
    fifo2_path = os.path.join(tmpdir, 'fifo2')
    with FIFOFeeder(feeder1, fifo1_path) as fifo1, \
            FIFOFeeder(feeder2, fifo2_path) as fifo2:
         FIFOFeeder(feeder2, fifo2_path, early_eval=True) as fifo2:
        return run_diff(fifo1_path, fifo2_path, fifo1.end_nl_q, fifo2.end_nl_q)