зеркало из https://github.com/github/ruby.git
merge revision(s) 3b83b265f11965582d4b9b439eff8a501792ab68: [Backport #19404]
YJIT: Crash with rb_bug() when panicking Helps with getting good bug reports in the wild. Intended to be backported to the 3.2.x series. --- yjit/bindgen/src/main.rs | 3 +++ yjit/src/cruby_bindings.inc.rs | 1 + yjit/src/yjit.rs | 29 +++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 2 deletions(-)
This commit is contained in:
Родитель
535d863f34
Коммит
3a88589399
|
@ -11,7 +11,7 @@
|
|||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
|
||||
#define RUBY_VERSION_TEENY 0
|
||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
|
||||
#define RUBY_PATCHLEVEL 26
|
||||
#define RUBY_PATCHLEVEL 27
|
||||
|
||||
#include "ruby/version.h"
|
||||
#include "ruby/internal/abi.h"
|
||||
|
|
|
@ -85,6 +85,9 @@ fn main() {
|
|||
// This function prints info about a value and is useful for debugging
|
||||
.allowlist_function("rb_obj_info_dump")
|
||||
|
||||
// For crashing
|
||||
.allowlist_function("rb_bug")
|
||||
|
||||
// From shape.h
|
||||
.allowlist_function("rb_shape_get_shape_id")
|
||||
.allowlist_function("rb_shape_get_shape_by_id")
|
||||
|
|
|
@ -1057,6 +1057,7 @@ extern "C" {
|
|||
pub fn rb_singleton_class(obj: VALUE) -> VALUE;
|
||||
pub fn rb_get_alloc_func(klass: VALUE) -> rb_alloc_func_t;
|
||||
pub fn rb_method_basic_definition_p(klass: VALUE, mid: ID) -> ::std::os::raw::c_int;
|
||||
pub fn rb_bug(fmt: *const ::std::os::raw::c_char, ...) -> !;
|
||||
pub fn rb_gc_writebarrier(old: VALUE, young: VALUE);
|
||||
pub fn rb_class_get_superclass(klass: VALUE) -> VALUE;
|
||||
pub static mut rb_mKernel: VALUE;
|
||||
|
|
|
@ -50,13 +50,13 @@ pub extern "C" fn rb_yjit_init_rust() {
|
|||
|
||||
// Catch panics to avoid UB for unwinding into C frames.
|
||||
// See https://doc.rust-lang.org/nomicon/exception-safety.html
|
||||
// TODO: set a panic handler so the we don't print a message
|
||||
// everytime we panic.
|
||||
let result = std::panic::catch_unwind(|| {
|
||||
Invariants::init();
|
||||
CodegenGlobals::init();
|
||||
YjitExitLocations::init();
|
||||
|
||||
rb_bug_panic_hook();
|
||||
|
||||
// YJIT enabled and initialized successfully
|
||||
YJIT_ENABLED.store(true, Ordering::Release);
|
||||
});
|
||||
|
@ -67,6 +67,31 @@ pub extern "C" fn rb_yjit_init_rust() {
|
|||
}
|
||||
}
|
||||
|
||||
/// At the moment, we abort in all cases we panic.
|
||||
/// To aid with getting diagnostics in the wild without requiring
|
||||
/// people to set RUST_BACKTRACE=1, register a panic hook that crash using rb_bug().
|
||||
/// rb_bug() might not be as good at printing a call trace as Rust's stdlib, but
|
||||
/// it dumps some other info that might be relevant.
|
||||
///
|
||||
/// In case we want to do start doing fancier exception handling with panic=unwind,
|
||||
/// we can revisit this later. For now, this helps to get us good bug reports.
|
||||
fn rb_bug_panic_hook() {
|
||||
use std::panic;
|
||||
use std::io::{stderr, Write};
|
||||
|
||||
// Probably the default hook. We do this very early during process boot.
|
||||
let previous_hook = panic::take_hook();
|
||||
|
||||
panic::set_hook(Box::new(move |panic_info| {
|
||||
// Not using `eprintln` to avoid double panic.
|
||||
let _ = stderr().write_all(b"ruby: YJIT has panicked. More info to follow...\n");
|
||||
|
||||
previous_hook(panic_info);
|
||||
|
||||
unsafe { rb_bug(b"YJIT panicked\0".as_ref().as_ptr() as *const raw::c_char); }
|
||||
}));
|
||||
}
|
||||
|
||||
/// Called from C code to begin compiling a function
|
||||
/// NOTE: this should be wrapped in RB_VM_LOCK_ENTER(), rb_vm_barrier() on the C side
|
||||
#[no_mangle]
|
||||
|
|
Загрузка…
Ссылка в новой задаче