Fix vterm Ctrl-D, add process-exit banner, improve crash reporter
ober
3923f26757f4f3c7dd3e1011de10d562dd4ea0b1
--- a/scripts/patch-jerboa-aws-compat.sh +++ b/scripts/patch-jerboa-aws-compat.sh @@ -1,5 +1,5 @@ -#!/usr/bin/env bash -set -euo pipefail +#!/bin/sh +set -eu root="${1:-$(cd "$(dirname "$0")/.." && pwd)}" jaws="$root/vendor/jerboa-aws/lib/jerboa-aws" --- a/vendor/qt_shim.cpp +++ b/vendor/qt_shim.cpp @@ -264,13 +264,9 @@ static inline void safe_write_str(int fd, const char* s) { (void)write(fd, s, len); } -static void crash_write_report(int sig, siginfo_t* si) { +static void crash_write_report_to_fd(int fd, int sig, siginfo_t* si) { char numbuf[32]; - // Write to crash log file - int fd = open(s_crash_log_path, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) fd = STDERR_FILENO; // fallback to stderr - safe_write_str(fd, "=== JEMACS CRASH REPORT ===\n"); safe_write_str(fd, "Signal: "); safe_itoa(numbuf, sizeof(numbuf), (long)sig); @@ -325,14 +321,19 @@ static void crash_write_report(int sig, siginfo_t* si) { safe_write_str(fd, "\n--- Native Backtrace ---\n"); safe_write_str(fd, "(not captured in signal handler; run stress-burn-static for gdb bt full)\n"); safe_write_str(fd, "\n=== END CRASH REPORT ===\n"); +} - // Also dump to stderr if we wrote to a file - if (fd != STDERR_FILENO) { +static void crash_write_report(int sig, siginfo_t* si) { + int fd = open(s_crash_log_path, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd >= 0) { + crash_write_report_to_fd(fd, sig, si); close(fd); - safe_write_str(STDERR_FILENO, "\n[jemacs] CRASH — report written to "); + } + crash_write_report_to_fd(STDERR_FILENO, sig, si); + if (fd >= 0) { + safe_write_str(STDERR_FILENO, "\n[jemacs] crash report also written to "); safe_write_str(STDERR_FILENO, s_crash_log_path); safe_write_str(STDERR_FILENO, "\n"); - } } @@ -7867,6 +7868,17 @@ protected: if (vtkey != VTERM_KEY_NONE) { vterm_keyboard_key(m_vt, vtkey, mod); handled = true; + } else if ((mod & VTERM_MOD_CTRL) && + ev->key() >= Qt::Key_A && ev->key() <= Qt::Key_Z) { + // Qt's ev->text() for Ctrl+letter is already the raw control byte + // (e.g. 0x04 for Ctrl-D). Falling into the generic unichar branch + // below would pass that 0x04 + VTERM_MOD_CTRL to libvterm, which + // interprets it as "modifyOtherKeys" and emits an ESC[4;5u CSI-u + // sequence instead of the raw 0x04. Re-encode as the letter + // codepoint so libvterm emits the canonical control byte. + uint32_t letter = ev->key() - Qt::Key_A + 'a'; + vterm_keyboard_unichar(m_vt, letter, mod); + handled = true; } else if (!ev->text().isEmpty()) { QString text = ev->text(); for (int i = 0; i < text.size(); i++) { @@ -7982,9 +7994,31 @@ private: int status; pid_t result = waitpid(m_child_pid, &status, WNOHANG); if (result == m_child_pid || result < 0) { + // Build a visible "[Process exited]" banner so the user + // sees that the shell actually died — otherwise the vterm + // just freezes at the last prompt and looks like a hang. + char banner[128]; + int n; + if (result == m_child_pid && WIFEXITED(status)) { + n = snprintf(banner, sizeof(banner), + "\r\n[Process exited (status %d)]\r\n", + WEXITSTATUS(status)); + } else if (result == m_child_pid && WIFSIGNALED(status)) { + n = snprintf(banner, sizeof(banner), + "\r\n[Process killed by signal %d]\r\n", + WTERMSIG(status)); + } else { + n = snprintf(banner, sizeof(banner), + "\r\n[Process exited]\r\n"); + } + if (n > 0 && m_vt) { + vterm_input_write(m_vt, banner, (size_t)n); + if (m_screen) vterm_screen_flush_damage(m_screen); + } + m_running = false; m_timer->stop(); - ::close(m_master_fd); + if (m_master_fd >= 0) ::close(m_master_fd); m_master_fd = -1; m_child_pid = -1; update();