Skip Menu |
Report information
Id: 131871
Status: open
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: smls75 [at] gmail.com
Cc:
AdminCc:

Severity: (no value)
Tag: testneeded
Platform: (no value)
Patch Status: (no value)
VM: (no value)



Subject: [CONC] [REGEX] Regex code block closing over lexical variable, is not threadsafe
From: Sam S <smls75 [...] gmail.com>
To: Rakudo Bugtracker <rakudobug [...] perl.org>
Date: Wed, 9 Aug 2017 22:06:32 +0200
This bug was found as a side-effect of RT #131870, but might be a separate issue: ➜ await ^10 .map: -> $i { start { "".match(/ { say $i } /) } } 7 7 6 6 7 8 9 9 9 9 Somehow, multiple iterations see the same value for the closed-over variable `$i`. Without the `await` and `start`, it prints each number from 0 to 9 exactly once, like it should. --- Note that the problem is only with *code blocks* inside regexes. When a lexical variable is interpolated into the top-level of a regex directly, things seem to work fine: ➜ say await ^10 .map: -> $i { start { "0123456789".match(/ $i /) } } (「0」 「1」 「2」 「3」 「4」 「5」 「6」 「7」 「8」 「9 --- Bot-friendly version that reliably prints `False`, even though it should print `True`: my $c = Channel.new; (await ^100 .map: -> $i { start "".match(/ { $c.send: $i } /) }); $c.close; say $c.sort.list eqv (^100).list; According to bisectable6 and committable6 this prints `False` for all past Perl 6 releases, so it's not a regression but rather an old bug.
Download (untitled) / with headers
text/plain 1.7k
On Wed, 09 Aug 2017 13:06:46 -0700, smls75@gmail.com wrote: Show quoted text
> This bug was found as a side-effect of RT #131870, but might be a > separate issue: > > ➜ await ^10 .map: -> $i { start { "".match(/ { say $i } /) } } > 7 > 7 > 6 > 6 > 7 > 8 > 9 > 9 > 9 > 9 >
Fixed with one or more of (better-sched) 7c18112c59d20413b82356e5c48b38d8a66fc7ea c285b489c6629ccdf0c4cb11d2d695b9ef1f890c 7fcab1067de4757bfdf2fdd1c66893ce4ab06e1b 89b9ac7830bdc195cb303f5241641e0dbe0ebbde 683037be698d0bdc21b3c23588085b2d076d7a0a b5605c2dd6d361b705a59136c8ad641f245a5da5 c50d35a90e66346157b31cd92643c2a64e801c24 de311f46a98f13a5b0211d2585fbd9b17ce1bf2c 340d8ed3bb4b45af85708771bea396cf862a7330 3b98fb9e396d040a8cb2c32d23cee54a5e88f878 596611c8fdc3baf119bc94a8ea30efc0a12cf673 80b49320cf854ac68a17cdd216575ee26e380325 61a77e60a7d936415503d8916fcc7546569e9135 Show quoted text
> Somehow, multiple iterations see the same value for the closed-over > variable `$i`. > > Without the `await` and `start`, it prints each number from 0 to 9 > exactly once, like it should. > > --- > > Note that the problem is only with *code blocks* inside regexes. When a > lexical variable is interpolated into the top-level of a regex directly, > things seem to work fine: > > ➜ say await ^10 .map: -> $i { start { "0123456789".match(/ $i /) } } > (「0」 「1」 「2」 「3」 「4」 「5」 「6」 「7」 「8」 「9 > > --- > > Bot-friendly version that reliably prints `False`, even though it should > print `True`: > > my $c = Channel.new; (await ^100 .map: -> $i { start "".match(/ { > $c.send: $i } /) }); $c.close; say $c.sort.list eqv (^100).list; > > According to bisectable6 and committable6 this prints `False` for all > past Perl 6 releases, so it's not a regression but rather an old bug.
OK, first of all, a bot-friendly (whateverable-friendly specifically) version of the first snippet is here:

say run(:out, <perl6 -e>, ‘await ^100 .map: -> $i { start { "".match(/ { print $i } /) } }’).out.slurp-rest eq (^100).join

And that points to the better-sched merge as noted by dogbert++

The second snippet is faulty in a completely different way, but it is also fixed.

So the second snippet is living its own life which is probably more interesting than mine:

On 2015.12 and onwards it was giving False. Then it was fixed (?) in:

(2017-12-19) https://github.com/rakudo/rakudo/commit/c51f1796e627e93b34e1b06b46c6dccb82549e04

and therefore started to give True. However, after this commit it got broken (?) again:

(2018-02-07) https://github.com/rakudo/rakudo/commit/c0c7756f4b5c1d5c79eea56a30a6e43b17b7d408

and therefore started to give False. But it didn't take long to fix that again in:

(2018-03-04) https://github.com/rakudo/rakudo/commit/fb882d498edec985a1bd645208862681a64c8743

and so now it gives True again.

Please write tests for this so that it does not get worse than that :)

***⚠ if you write tests, please test both snippets ⚠***

On 2017-08-09 13:06:46, smls75@gmail.com wrote:
Show quoted text
> This bug was found as a side-effect of RT #131870, but might be a
> separate issue:
>
> ➜ await ^10 .map: -> $i { start { "".match(/ { say $i } /) } }
> 7
> 7
> 6
> 6
> 7
> 8
> 9
> 9
> 9
> 9
>
> Somehow, multiple iterations see the same value for the closed-over
> variable `$i`.
>
> Without the `await` and `start`, it prints each number from 0 to 9
> exactly once, like it should.
>
> ---
>
> Note that the problem is only with *code blocks* inside regexes. When a
> lexical variable is interpolated into the top-level of a regex directly,
> things seem to work fine:
>
> ➜ say await ^10 .map: -> $i { start { "0123456789".match(/ $i /) } }
> (「0」 「1」 「2」 「3」 「4」 「5」 「6」 「7」 「8」 「9
>
> ---
>
> Bot-friendly version that reliably prints `False`, even though it should
> print `True`:
>
> my $c = Channel.new; (await ^100 .map: -> $i { start "".match(/ {
> $c.send: $i } /) }); $c.close; say $c.sort.list eqv (^100).list;
>
> According to bisectable6 and committable6 this prints `False` for all
> past Perl 6 releases, so it's not a regression but rather an old bug.




This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org