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

Control exception handling is inconsistent and broken across backends. (SEGV on moar, CX unrecognized on jvm) #4688

Closed
p6rt opened this issue Oct 29, 2015 · 12 comments

Comments

@p6rt
Copy link

p6rt commented Oct 29, 2015

Migrated from rt.perl.org#126490 (status was 'resolved')

Searchable as RT126490$

@p6rt
Copy link
Author

p6rt commented Oct 29, 2015

From @peschwa

R-J currently fails in about five files in roast with "control exception without handler", golfable as follows​:

16​:08 <psch> r​: A​: for 1 { for 1 { last A } };
16​:08 <camelia> rakudo-jvm 3cc195​: OUTPUT«===SORRY!===␤control exception without handler␤»
16​:08 <camelia> ..rakudo-moar 3cc195​: ( no output )

Digging around a bit showed that in this specific case the exception is of type 4104, e.g. last_labeled, which clearly is correct.

The case of last-ing out of the current loop (with or without label) works, as follows​:

16​:12 <psch> j​: A​: for 1 { last A }; for 1 { last }
16​:12 <camelia> rakudo-jvm 3cc195​: ( no output )

Installing a CONTROL block in the labeled loop in the first case works somewhat as expected, the exception is caught, but doesn't identify itself as CX​::Last​:

16​:15 <psch> j​: A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }
16​:15 <camelia> rakudo-jvm 3cc195​: OUTPUT«X​::AdHoc.new(payload => "Died")␤»

The same code on R-M segfaults​:

16​:15 <psch> m​: A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }
16​:15 <camelia> rakudo-moar 3cc195​: OUTPUT«(signal SEGV)»

I have looked at the R-J and NQP-J CX handling, and have the suspicion that responsibility partly lies with org.perl6.nqp.runtime.ExceptionHandling​:90, where it's decided not to use a handler if it's from the current frame. The corresponding code in Moar is beyond my C-understanding, but I further suspect that either the condition for discarding a possibly valid handler is different, or that codegen on moar inserts handlers differently.

Also of note might be that neither NQP implements labeled loops themselves, even though it's from NQP​::Grammar and NQP​::Actions that we get handling of last/next/redo in the first place.

@p6rt
Copy link
Author

p6rt commented Oct 29, 2015

From @nwc10

On Thu, Oct 29, 2015 at 09​:22​:30AM -0700, Pepe Schwarz wrote​:

The same code on R-M segfaults​:

16​:15 <psch> m​: A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }
16​:15 <camelia> rakudo-moar 3cc195​: OUTPUT«(signal SEGV)»

$ ./perl6-m -Ilib -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
ASAN​:SIGSEGV

==28758==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000024 (pc 0x7f88780c7391 sp 0x7fff1a233990 bp 0x7fff1a2339a0 T0)
  #​0 0x7f88780c7390 in MVM_string_graphs src/strings/ops.h​:30
  #​1 0x7f88780e7dcd in MVM_interp_run src/core/interp.c​:1491
  #​2 0x7f8878398003 in MVM_vm_run_file src/moar.c​:249
  #​3 0x401a4f in main src/main.c​:191
  #​4 0x7f887792ad5c in __libc_start_main (/lib64/libc.so.6+0x1ed5c)
  #​5 0x401058 (/home/nicholas/Sandpit/moar-san/bin/moar+0x401058)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV src/strings/ops.h​:30 MVM_string_graphs
==28758==ABORTING

Looks like it's "just" a NULL pointer dereference.

Nicholas Clark

@p6rt
Copy link
Author

p6rt commented Oct 29, 2015

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

@p6rt
Copy link
Author

p6rt commented Oct 30, 2015

From @nwc10

On Thu, Oct 29, 2015 at 07​:41​:06PM +0000, Nicholas Clark wrote​:

On Thu, Oct 29, 2015 at 09​:22​:30AM -0700, Pepe Schwarz wrote​:

The same code on R-M segfaults​:

16​:15 <psch> m​: A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }
16​:15 <camelia> rakudo-moar 3cc195​: OUTPUT«(signal SEGV)»

$ ./perl6-m -Ilib -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
ASAN​:SIGSEGV

==28758==ERROR​: AddressSanitizer​: SEGV on unknown address 0x000000000024 (pc 0x7f88780c7391 sp 0x7fff1a233990 bp 0x7fff1a2339a0 T0)
#​0 0x7f88780c7390 in MVM_string_graphs src/strings/ops.h​:30
#​1 0x7f88780e7dcd in MVM_interp_run src/core/interp.c​:1491
#​2 0x7f8878398003 in MVM_vm_run_file src/moar.c​:249
#​3 0x401a4f in main src/main.c​:191
#​4 0x7f887792ad5c in __libc_start_main (/lib64/libc.so.6+0x1ed5c)
#​5 0x401058 (/home/nicholas/Sandpit/moar-san/bin/moar+0x401058)

AddressSanitizer can not provide additional info.
SUMMARY​: AddressSanitizer​: SEGV src/strings/ops.h​:30 MVM_string_graphs
==28758==ABORTING

Looks like it's "just" a NULL pointer dereference.

valgrind concurs​:

$ valgrind /home/nicholas/Sandpit/moar-g/bin/moar --libpath="/home/nicholas/Sandpit/moar-g/share/nqp/lib" --libpath="." /home/nicholas/Perl/rakudo/perl6.moarvm -Ilib -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
==25743== Memcheck, a memory error detector
==25743== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==25743== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==25743== Command​: /home/nicholas/Sandpit/moar-g/bin/moar --libpath=/home/nicholas/Sandpit/moar-g/share/nqp/lib --libpath=. /home/nicholas/Perl/rakudo/perl6.moarvm -Ilib -e A​:\ for\ 1\ {\ for\ 1\ {\ last\ A\ };\ CONTROL\ {\ when\ CX​::Last\ {\ say\ "last"\ };\ default\ {\ .perl.say\ }\ }\ }
==25743==
==25743== Invalid read of size 4
==25743== at 0x4F7E95A​: MVM_string_graphs (ops.h​:30)
==25743== by 0x4F88DDB​: MVM_interp_run (interp.c​:1491)
==25743== by 0x5080950​: MVM_vm_run_file (moar.c​:249)
==25743== by 0x401280​: main (main.c​:191)
==25743== Address 0x24 is not stack'd, malloc'd or (recently) free'd
==25743==
==25743==
==25743== Process terminating with default action of signal 11 (SIGSEGV)
==25743== Access not within mapped region at address 0x24
==25743== at 0x4F7E95A​: MVM_string_graphs (ops.h​:30)
==25743== by 0x4F88DDB​: MVM_interp_run (interp.c​:1491)
==25743== by 0x5080950​: MVM_vm_run_file (moar.c​:249)
==25743== by 0x401280​: main (main.c​:191)
==25743== If you believe this happened as a result of a stack
==25743== overflow in your program's main thread (unlikely but
==25743== possible), you can try to increase the size of the
==25743== main thread stack using the --main-stacksize= flag.
==25743== The main thread stack size used in this run was 10485760.
==25743==
==25743== HEAP SUMMARY​:
==25743== in use at exit​: 53,962,132 bytes in 213,579 blocks
==25743== total heap usage​: 233,496 allocs, 19,917 frees, 69,014,035 bytes allocated
==25743==
==25743== LEAK SUMMARY​:
==25743== definitely lost​: 36,954 bytes in 673 blocks
==25743== indirectly lost​: 21,240 bytes in 681 blocks
==25743== possibly lost​: 175,280 bytes in 3,133 blocks
==25743== still reachable​: 53,728,658 bytes in 209,092 blocks
==25743== suppressed​: 0 bytes in 0 blocks
==25743== Rerun with --leak-check=full to see details of leaked memory
==25743==
==25743== For counts of detected and suppressed errors, rerun with​: -v
==25743== ERROR SUMMARY​: 1 errors from 1 contexts (suppressed​: 9 from 9)
Segmentation fault

Nicholas Clark

@p6rt
Copy link
Author

p6rt commented Nov 6, 2015

From @usev6

As a status update​: This code no longer segfaults on Moar​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
chars requires a concrete string, but got null
  in block at -e​:1
  in block at -e​:1
  in block <unit> at -e​:1

1 similar comment
@p6rt
Copy link
Author

p6rt commented Nov 6, 2015

From @usev6

As a status update​: This code no longer segfaults on Moar​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
chars requires a concrete string, but got null
  in block at -e​:1
  in block at -e​:1
  in block <unit> at -e​:1

@p6rt
Copy link
Author

p6rt commented Jul 16, 2016

From @usev6

I unfudged one test for this ticket in S04-statements/label.t with commit Raku/roast@ef7b0da83d

The code that used to segfault works fine now​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
last

$ perl6-j -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
last

The mentioned failing tests for rakudo-j are still a thing, tough.

1 similar comment
@p6rt
Copy link
Author

p6rt commented Jul 16, 2016

From @usev6

I unfudged one test for this ticket in S04-statements/label.t with commit Raku/roast@ef7b0da83d

The code that used to segfault works fine now​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
last

$ perl6-j -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last { say "last" }; default { .perl.say } } }'
last

The mentioned failing tests for rakudo-j are still a thing, tough.

@p6rt
Copy link
Author

p6rt commented Oct 16, 2017

From @usev6

On Sat, 16 Jul 2016 13​:18​:42 -0700, bartolin@​gmx.de wrote​:

I unfudged one test for this ticket in S04-statements/label.t with
commit Raku/roast@ef7b0da83d

The code that used to segfault works fine now​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last {
say "last" }; default { .perl.say } } }'
last

$ perl6-j -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last {
say "last" }; default { .perl.say } } }'
last

The mentioned failing tests for rakudo-j are still a thing, tough.

The remaining tests fudged with this ticket are passing with rakudo-j now. I unfudged them with commit Raku/roast@07517a0006

@p6rt
Copy link
Author

p6rt commented Mar 12, 2018

From @dogbert17

On Mon, 16 Oct 2017 13​:04​:48 -0700, bartolin@​gmx.de wrote​:

On Sat, 16 Jul 2016 13​:18​:42 -0700, bartolin@​gmx.de wrote​:

I unfudged one test for this ticket in S04-statements/label.t with
commit Raku/roast@ef7b0da83d

The code that used to segfault works fine now​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last {
say "last" }; default { .perl.say } } }'
last

$ perl6-j -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last {
say "last" }; default { .perl.say } } }'
last

The mentioned failing tests for rakudo-j are still a thing, tough.

The remaining tests fudged with this ticket are passing with rakudo-j
now. I unfudged them with commit
Raku/roast@07517a0006

Fixed with commit rakudo/rakudo@1fbb8b4
at least on MoarVM.

@p6rt
Copy link
Author

p6rt commented Apr 7, 2018

From @AlexDaniel

Segfault mentioned above is already tested and the test was unfudged in
Raku/roast@ef7b0da83d#diff-72b101ff62a0582672d4de2788ffa1bbL77

Closing
On 2018-03-12 08​:29​:49, jan-olof.hendig@​bredband.net wrote​:

On Mon, 16 Oct 2017 13​:04​:48 -0700, bartolin@​gmx.de wrote​:

On Sat, 16 Jul 2016 13​:18​:42 -0700, bartolin@​gmx.de wrote​:

I unfudged one test for this ticket in S04-statements/label.t with
commit Raku/roast@ef7b0da83d

The code that used to segfault works fine now​:

$ perl6-m -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last
{
say "last" }; default { .perl.say } } }'
last

$ perl6-j -e 'A​: for 1 { for 1 { last A }; CONTROL { when CX​::Last
{
say "last" }; default { .perl.say } } }'
last

The mentioned failing tests for rakudo-j are still a thing, tough.

The remaining tests fudged with this ticket are passing with rakudo-j
now. I unfudged them with commit
Raku/roast@07517a0006

Fixed with commit
rakudo/rakudo@1fbb8b4
at least on MoarVM.

@p6rt
Copy link
Author

p6rt commented Apr 7, 2018

@AlexDaniel - Status changed from 'open' to 'resolved'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant