Skip to content

fix(it2check): Set timeout so read does not hang - #702

Open
mattmartini wants to merge 1 commit into
gnachman:masterfrom
mattmartini:master
Open

fix(it2check): Set timeout so read does not hang#702
mattmartini wants to merge 1 commit into
gnachman:masterfrom
mattmartini:master

Conversation

@mattmartini

Copy link
Copy Markdown

See GitLab Issue: gnachman/iterm2#12934

Utility it2check hangs when run as root in bash 5.2.21

  • iTerm2 version: 3.6.11
  • OS version: macOS 26.5 (Tahoe)

Running it2check as root under bash 5.2.21 hangs. Regular users can run this without a problem.

I discovered this issue after upgrading a server from Ubuntu 22.04 (running bash 5.1.16(1)-release) to Ubuntu 24.04 (running bash 5.2.21(1)-release). In my .bash_profile I run it2check to decide how to set some ENV vars. Logging into the upgraded server, sessions hang. I traced the problem to:

It gets stuck at line 50
while read none; do :; done

It seems that there is issue with this in bash.

The fix for the issue is to set a timeout on the read. I also set max chars.

while read -t 0.1 -n 10000 none; do :; done

I am sending a pull request on GitHub with my changes.

My solution was inspired by: clear-stdin-before-reading

Detailed steps to reproduce the problem:

  1. login as root
  2. run it2check

What happened:
the session hangs with no way out as ctrl-c and other remidies are captured and ignored.

What should have happened:
It returns after assessing if you are running iTerm2.

@gnachman

Copy link
Copy Markdown
Owner

Thanks for tracking this down and for the clear write-up.

Two things before this can land:

1. The source of truth for this file is a different repo. OtherResources/Utilities/it2check in this repo is copied in from https://github.com/gnachman/iTerm2-shell-integration, so a change here would get overwritten on the next sync. The fix needs to be made in iTerm2-shell-integration instead (and it will then flow back into this repo).

2. Fractional read -t is not portable to bash < 4.0. The -n 10000 flag is fine, but the fractional -t 0.1 timeout was only added in bash 4.0. The script's shebang is #!/usr/bin/env bash, so it runs under whatever bash is first in PATH, which on a stock macOS box (no Homebrew) is the system /bin/bash 3.2.57. There:

$ /bin/bash -c 'while read -t 0.1 -n 10000 none; do :; done < /dev/null; echo exit=$?'
/bin/bash: line 0: read: 0.1: invalid timeout specification
exit=0

So on bash 3.2 the patched line prints an error to stderr on every run and read fails immediately, meaning the input-drain loop becomes a no-op. The original while read none worked silently there (with stty ... min 0 time 0, read returns at EOF). So as written this trades the bash-5.2 hang for a bash-3.2 regression.

A version-guarded form keeps the fast path where it is available and falls back to the old behavior otherwise:

if [ "${BASH_VERSINFO[0]:-0}" -ge 4 ]; then
  while read -t 0.1 -n 10000 none; do :; done
else
  while read -n 10000 none; do :; done
fi

Could you re-open this against iTerm2-shell-integration with a portable form? Happy to help review it there.

@mattmartini

Copy link
Copy Markdown
Author

George,

I made the pull-request from iTerm2-shell-intergration as you requested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants