Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regex code block closing over lexical variable, is not threadsafe #6437

Open
p6rt opened this issue Aug 9, 2017 · 4 comments
Open

Regex code block closing over lexical variable, is not threadsafe #6437

p6rt opened this issue Aug 9, 2017 · 4 comments
Labels
conc regex Regular expressions, pattern matching, user-defined grammars, tokens and rules testneeded

Comments

@p6rt
Copy link

p6rt commented Aug 9, 2017

Migrated from rt.perl.org#131871 (status was 'open')

Searchable as RT131871$

@p6rt
Copy link
Author

p6rt commented Aug 9, 2017

From @smls

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.

@p6rt
Copy link
Author

p6rt commented Mar 11, 2018

From @dogbert17

On Wed, 09 Aug 2017 13​:06​:46 -0700, smls75@​gmail.com wrote​:

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

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.

@p6rt
Copy link
Author

p6rt commented Mar 11, 2018

The RT System itself - Status changed from 'new' to 'open'

@p6rt
Copy link
Author

p6rt commented Mar 11, 2018

From @AlexDaniel

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) rakudo/rakudo@c51f179

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

(2018-02-07) rakudo/rakudo@c0c7756

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

(2018-03-04) rakudo/rakudo@fb882d4

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​:

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.

@p6rt p6rt added conc regex Regular expressions, pattern matching, user-defined grammars, tokens and rules testneeded labels Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
conc regex Regular expressions, pattern matching, user-defined grammars, tokens and rules testneeded
Projects
None yet
Development

No branches or pull requests

1 participant