You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
END { } crashes the process with a Go panic: valid Ruby source takes the embedder's host down #805
END { } — ordinary Ruby, in the language since 1.0 — ends the process with an
uncontained Go runtime panic:
$ cat p.rbEND { puts "E" }
$ rbgo p.rbpanic: runtime error: slice bounds out of range [:1] with capacity 0 [recovered, repanicked]
$ echo$?2
MRI prints E and exits 0.
For a program this is a crash instead of an answer. For an embedder it is
worse: ruby.Run does not return an error, it takes the host process down,
and nothing the host can write around the call prevents it.
Isolated
source
rbgo
BEGIN { puts "B" } + puts "main"
B, main — correct
at_exit { puts "A" }
main, A — correct
at_exit { |x| puts x.inspect }
nil — correct
END { puts "E" }
panic, exit 2
END { 1 }; puts "ok"
prints ok, then panics
END { } ×2
panic
The last row of that table is the useful one: the block registers fine and
the program runs to completion — ok is printed — and the panic happens when
the handler is invoked at exit.
capacity 0 with nbind == 1 says env.slots is empty while the ISeq claims a
parameter slot. So the END block's ISeq and its environment disagree about how
many locals it has — and at_exit, whose block takes the same path with the
same zero arguments, does not, which is what points at how END is compiled
rather than at the binder.
The repanic at vm.go:1523 is not the bug
That arm is deliberate policy, and TestRunPropagatesInternalPanic encodes it:
a fault built from Ruby input is converted to a Ruby exception, while a
broken VM invariant stays loud rather than being dressed up as a RuntimeError the program might rescue. This is an inconsistent ISeq, which is
the second kind. The fix belongs where the ISeq is built, not in the recover.
The README says something else, and it is the kinder story
BEGIN { } / END { } — do not parse (parse error: unexpected "{" after statement).
Measured today, BEGIN { }works and END { } parses and then crashes. A
reader checking whether they can use it is told it is unavailable, which is a
gap; what they get is a process death. Being corrected in #801.
Activity
README: two more rows re-measured, and one of them was understating a…
README: drop two limitations the repository already disproved, add tw…
fix: an END block records no splat, instead of claiming one at index 0 (