···1313CACHE_KEY="pinentry-rofi-pin"
1414CACHE_TIMEOUT=300 # 5 minutes
15151616+# Hard limit on how long a dialog may sit unanswered. Without it, a prompt
1717+# nobody answers (lost workspace, requester already dead) hangs forever, and
1818+# ssh-tpm-agent serializes TPM access behind it: every later signature blocks,
1919+# so all ssh auth on the machine wedges until the stray rofi is killed by hand.
2020+# On expiry `timeout` exits 124, which the callers treat like a cancel, so the
2121+# requester gets a failed auth it can retry instead of a deadlock.
2222+PROMPT_TIMEOUT="${PINENTRY_ROFI_TIMEOUT:-120}"
2323+1624# ---------- cache helpers ----------
17251826get_cached_pin() {
···106114 local cached_pin=""
107115 if cached_pin=$(get_cached_pin 2>/dev/null) && [[ -n "$cached_pin" ]]; then
108116 local choice
109109- choice=$(printf "OK\nCancel\nClear cache" | rofi -dmenu \
117117+ choice=$(printf "OK\nCancel\nClear cache" | timeout -k 5 "$PROMPT_TIMEOUT" rofi -dmenu \
110118 -i \
111119 -no-custom \
112120 -no-fixed-num-lines \
···131139 fi
132140133141 local result
134134- result=$(rofi -dmenu \
142142+ result=$(timeout -k 5 "$PROMPT_TIMEOUT" rofi -dmenu \
135143 -password \
136144 -p "$prompt_label" \
137145 -lines 0 \