(signum: libc::c_int)
| 497 | // faulthandler_fatal_error |
| 498 | #[cfg(unix)] |
| 499 | extern "C" fn faulthandler_fatal_error(signum: libc::c_int) { |
| 500 | let save_errno = get_errno(); |
| 501 | |
| 502 | if !FATAL_ERROR.enabled.load(Ordering::Relaxed) { |
| 503 | return; |
| 504 | } |
| 505 | |
| 506 | let fd = FATAL_ERROR.fd.load(Ordering::Relaxed); |
| 507 | |
| 508 | let handler = unsafe { |
| 509 | FAULTHANDLER_HANDLERS |
| 510 | .iter_mut() |
| 511 | .find(|h| h.signum == signum) |
| 512 | }; |
| 513 | |
| 514 | if let Some(h) = handler { |
| 515 | // Disable handler (restores previous) |
| 516 | unsafe { |
| 517 | faulthandler_disable_fatal_handler(h); |
| 518 | } |
| 519 | |
| 520 | puts(fd, "Fatal Python error: "); |
| 521 | puts(fd, h.name); |
| 522 | puts(fd, "\n\n"); |
| 523 | } else { |
| 524 | puts(fd, "Fatal Python error from unexpected signum: "); |
| 525 | dump_decimal(fd, signum as usize); |
| 526 | puts(fd, "\n\n"); |
| 527 | } |
| 528 | |
| 529 | let all_threads = FATAL_ERROR.all_threads.load(Ordering::Relaxed); |
| 530 | faulthandler_dump_traceback(fd, all_threads); |
| 531 | |
| 532 | set_errno(save_errno); |
| 533 | |
| 534 | // Reset to default handler and re-raise to ensure process terminates. |
| 535 | // We cannot just restore the previous handler because Rust's runtime |
| 536 | // may have installed its own SIGSEGV handler (for stack overflow detection) |
| 537 | // that doesn't terminate the process on software-raised signals. |
| 538 | unsafe { |
| 539 | libc::signal(signum, libc::SIG_DFL); |
| 540 | libc::raise(signum); |
| 541 | } |
| 542 | |
| 543 | // Fallback if raise() somehow didn't terminate the process |
| 544 | unsafe { |
| 545 | libc::_exit(1); |
| 546 | } |
| 547 | } |
| 548 | |
| 549 | // faulthandler_fatal_error for Windows |
| 550 | #[cfg(windows)] |
nothing calls this directly
no test coverage detected