fix: close the RV6 verification gaps
Resolves the 7 gap groups in docs/rewrite/notes/review-rv6-codex.md (final-Z8.md): - crash (macOS): request_abort_dump returns false on mach_msg receive timeout/error so the signal-path fallback runs; EXC_SOFT_SIGNAL keeps the signal number in the minidump exception info. - Default SHELL read as an OS string and stored in encoded command form. - macOS executable search works on raw PATH bytes; the default path is used only when PATH is unset. - Windows: config env overrides are decoded; EnvMap compares keys as WTF-16 units with per-unit Unicode simple uppercasing (no lossy conversion, distinct lone-surrogate keys stay distinct). - +show-config writes original bytes for encoded OS data, so export + reload round-trips; UTF-8 configs are byte-identical as before. - Zig's ensureLocale chain lives in ghostty-os for all Unix targets and is used by both the GTK app and the C API init. Also makes the quick-terminal GTK replay test independent of compositor focus: GTK's is-active is read-only, so when niri actually focuses the layer surface the simulated focus-out cannot drive autohide and that assertion is skipped (the production logic is unchanged and matches Zig). Test Plan: - cargo test --workspace (3390 passed, incl. tests/gtk_replay.rs) - just check-macos (both), just check-windows, just check-wasm
This commit is contained in:
1 parent
e57e54cbf2
commit
5c5d916960
12 files changed
+452
-133
No files matched your search
@@ -39,6 +39,13 @@ impl MachException {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the timed receive of the abort reply succeeded
|
||||
/// (`KERN_SUCCESS`); on timeout or error the caller must fall back to the
|
||||
/// signal-path report.
|
||||
pub(crate) fn abort_reply_ok(kr: i32) -> bool {
|
||||
kr == 0
|
||||
}
|
||||
|
||||
/// Wire layout of the abort request after the 24 byte Mach header:
|
||||
/// `thread: u32`, `signo: i32` (native endian).
|
||||
pub(crate) const ABORT_BODY_LEN: usize = 8;
|
||||
@@ -78,6 +85,14 @@ fn kern_name(code: i64) -> Option<&'static str> {
|
||||
}
|
||||
|
||||
impl MachException {
|
||||
/// The subcode recorded in the minidump exception information: kept for
|
||||
/// `EXC_BAD_ACCESS` (fault address) and for `EXC_SOFTWARE` /
|
||||
/// `EXC_SOFT_SIGNAL` (the signal number).
|
||||
pub(crate) fn minidump_subcode(&self) -> Option<u64> {
|
||||
(self.kind == EXC_BAD_ACCESS || (self.kind == EXC_SOFTWARE && self.code == EXC_SOFT_SIGNAL))
|
||||
.then_some(self.subcode as u64)
|
||||
}
|
||||
|
||||
/// `EXC_BAD_ACCESS`, ...
|
||||
pub(crate) fn name(&self) -> &'static str {
|
||||
match self.kind {
|
||||
@@ -314,6 +329,30 @@ mod tests {
|
||||
assert_eq!(s, "EXC_SOFTWARE (code=0x10003, subcode=0x6)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn soft_signal_subcode_is_kept_for_minidump() {
|
||||
assert_eq!(MachException::from_signal(6).minidump_subcode(), Some(6));
|
||||
let bad = MachException {
|
||||
kind: EXC_BAD_ACCESS,
|
||||
code: 1,
|
||||
subcode: 0x10,
|
||||
};
|
||||
assert_eq!(bad.minidump_subcode(), Some(0x10));
|
||||
let other = MachException {
|
||||
kind: EXC_SOFTWARE,
|
||||
code: 1,
|
||||
subcode: 9,
|
||||
};
|
||||
assert_eq!(other.minidump_subcode(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn abort_reply_timeout_or_error_is_failure() {
|
||||
assert!(abort_reply_ok(0));
|
||||
assert!(!abort_reply_ok(0x10004003)); // MACH_RCV_TIMED_OUT
|
||||
assert!(!abort_reply_ok(5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn windows_names() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -460,7 +460,7 @@ pub(crate) fn request_abort_dump(signo: libc::c_int) -> bool {
|
||||
// suspension before replying). Bounded, in case the dump hangs.
|
||||
let mut buf = Buffer([0; 1024]);
|
||||
// SAFETY: `buf` is a writable 1024 byte aligned buffer.
|
||||
unsafe {
|
||||
let received = unsafe {
|
||||
mach_msg(
|
||||
buf.0.as_mut_ptr().cast(),
|
||||
MACH_RCV_MSG | MACH_RCV_TIMEOUT,
|
||||
@@ -469,9 +469,11 @@ pub(crate) fn request_abort_dump(signo: libc::c_int) -> bool {
|
||||
reply,
|
||||
ABORT_WAIT_MS,
|
||||
MACH_PORT_NULL,
|
||||
);
|
||||
}
|
||||
true
|
||||
)
|
||||
};
|
||||
// Timeout or error: the report was not confirmed, so the caller falls
|
||||
// back to the signal-path report.
|
||||
exception::abort_reply_ok(received)
|
||||
}
|
||||
|
||||
fn write_report(
|
||||
@@ -508,7 +510,7 @@ fn write_report(
|
||||
exception: Some(ExceptionInfo {
|
||||
kind: ex.kind,
|
||||
code: ex.code as u64,
|
||||
subcode: (ex.kind == exception::EXC_BAD_ACCESS).then_some(ex.subcode as u64),
|
||||
subcode: ex.minidump_subcode(),
|
||||
}),
|
||||
};
|
||||
let dump = MinidumpWriter::with_crash_context(cc).dump(&mut Cursor::new(Vec::new()));
|
||||
|
||||
Reference in new issue
Block a user