[PATCH V2] revset: fix generatorset race condition

Augie Fackler raf at durin42.com
Wed Mar 26 16:04:00 CDT 2014


Crewed this, thanks.

On Mar 25, 2014, at 8:33 PM, Durham Goode <durham at fb.com> wrote:

> # HG changeset patch
> # User Durham Goode <durham at fb.com>
> # Date 1395789007 25200
> #      Tue Mar 25 16:10:07 2014 -0700
> # Node ID c28ab989810ae838379b8964dbdd53a300a53c92
> # Parent  9a09a625bc93ab69248613abcbea041b785f1a0e
> revset: fix generatorset race condition
> 
> If two things were iterating over a generatorset at the same time, they could
> miss out on the things the other was generating, resulting in incomplete
> results. This fixes it by making it possible for two things to iterate at once,
> by always checking the _genlist at the beginning of each iteration.
> 
> I was only able to repro it with pending changes from my other commits, but they
> aren't ready yet. So I'm unable to add a test for now.
> 
> diff --git a/mercurial/revset.py b/mercurial/revset.py
> --- a/mercurial/revset.py
> +++ b/mercurial/revset.py
> @@ -2624,10 +2624,8 @@
>         gen: a generator producing the values for the generatorset.
>         """
>         self._gen = gen
> -        self._iter = iter(gen)
>         self._cache = {}
>         self._genlist = baseset([])
> -        self._iterated = False
>         self._finished = False
> 
>     def __contains__(self, x):
> @@ -2639,28 +2637,30 @@
>             if l == x:
>                 return True
> 
> -        self._finished = True
>         self._cache[x] = False
>         return False
> 
>     def __iter__(self):
> -        if self._iterated:
> -            # At least a part of the list should be cached if iteration has
> -            # started over the generatorset.
> -            for l in self._genlist:
> -                yield l
> -
> -        for item in self._consumegen():
> -            yield item
> +        if self._finished:
> +            for x in self._genlist:
> +                yield x
> +            return
> +
> +        i = 0
> +        genlist = self._genlist
> +        consume = self._consumegen()
> +        while True:
> +            if i < len(genlist):
> +                yield genlist[i]
> +            else:
> +                yield consume.next()
> +            i += 1
> 
>     def _consumegen(self):
> -        self._iterated = True
> -
>         for item in self._gen:
>             self._cache[item] = True
>             self._genlist.append(item)
>             yield item
> -
>         self._finished = True
> 
>     def set(self):
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20140326/ea2e138a/attachment.pgp>


More information about the Mercurial-devel mailing list