From 078a76f263a4a79c7f8e66215bdb46195a173251 Mon Sep 17 00:00:00 2001 From: MickLesk Date: Wed, 5 Aug 2026 14:57:15 +0200 Subject: [PATCH] Extract reclaim_tty into reusable function Move the inline TTY reclamation logic from build.func into a standalone reclaim_tty() function in core.func. This improves code reusability, as the function now needs to be called before each interactive prompt (not just after install) since pct exec/pull/enter can take the terminal away again. The function also includes better error handling with checks for perl availability and /dev/tty existence, and explicitly sets SIGTTOU to IGNORE in perl. --- misc/build.func | 17 ++++++++--------- misc/core.func | 33 +++++++++++++++++++++++++++++++++ misc/error_handler.func | 1 + 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/misc/build.func b/misc/build.func index 896d8c726..0f2b30015 100644 --- a/misc/build.func +++ b/misc/build.func @@ -5200,15 +5200,11 @@ EOF # TSTP = Ctrl+Z, TTIN = bg read from tty, TTOU = bg write to tty (tostop) trap '' TSTP TTIN TTOU - # lxc-attach takes the controlling terminal while the install runs and does - # not hand it back, leaving us in a background process group. Reading from - # the terminal then returns EIO instead of blocking, because SIGTTIN is - # ignored above - so every recovery prompt fails before the user can answer. - # Redirecting to /dev/tty does not help: the rule applies to the terminal, - # not the file descriptor. Claim the foreground group back; SIGTTOU is - # ignored too, so tcsetpgrp() succeeds instead of stopping us. No-op when we - # already are in the foreground. perl is a hard dependency of Proxmox VE. - perl -e 'use POSIX; open(my $t, "+<", "/dev/tty") or exit 1; POSIX::tcsetpgrp(fileno($t), getpgrp()) or exit 1;' 2>/dev/null || true + # lxc-attach left us in a background process group - claim the terminal back + # before we print anything. Note this does NOT hold: the log collection + # below uses pct pull/exec, which take it away again, so every interactive + # prompt has to reclaim it again right before its read. + reclaim_tty msg_error "Installation failed in container ${CTID} (exit code: ${install_exit_code})" @@ -5338,6 +5334,7 @@ EOF pct enter "$CTID" echo "" echo -en "${YW}Container ${CTID} still running. Remove now? (y/N): ${CL}" + reclaim_tty if read -r response /dev/null || true pct destroy "$CTID" &>/dev/null || true @@ -5497,6 +5494,7 @@ EOF local response="" local read_rc + reclaim_tty read -t 60 -r response " prompt /dev/null 2>&1 || return 0 + [[ -e /dev/tty ]] || return 0 + + local pgid + pgid=$(ps -o pgid= -p $$ 2>/dev/null | tr -d ' ') || true + + perl -e ' + use POSIX; + $SIG{TTOU} = "IGNORE"; + my $pgid = $ARGV[0] || POSIX::getpgrp(); + open(my $t, "+<", "/dev/tty") or exit 1; + POSIX::tcsetpgrp(fileno($t), $pgid) or exit 1; + ' "${pgid:-0}" 2>/dev/null || true +} + # ------------------------------------------------------------------------------ # is_alpine() # diff --git a/misc/error_handler.func b/misc/error_handler.func index ed972de9f..85ccba21b 100644 --- a/misc/error_handler.func +++ b/misc/error_handler.func @@ -499,6 +499,7 @@ error_handler() { local response="" local read_rc + declare -f reclaim_tty >/dev/null 2>&1 && reclaim_tty read -t 60 -r response