On Mon, 2010-03-22 at 19:07 +0000, Freddy Vulto wrote:
> Crestez Dan Leonard <cdleonard <at> gmail.com> writes:
> > I had to mangle +o posix to get tests to pass. I don't know why the test
> > suite puts the shell into posix mode anyway.
>
> Because users 'out there' might run bash-completion in bash POSIX mode. I
> regard POSIX as just stricter bash script and supportable with little effort,
> so
> I put it in the test suite to make sure bash-completion honours POSIX. A
> notable error is that POSIX doesn't allow a hyphen (-) in a function name,
> whereas standard bash does allow:
>
> $ f-a() { echo foo; }
> $ set -o posix
> $ f-a() { echo foo; }
> bash: `f-a': not a valid identifier
>
> Perhaps the test suite should test completions both with and without POSIX
> mode...
>
> Another solution - if bash-completion really demands noPOSIX :-( - could be to
> disable POSIX on entering bash-completion and restore POSIX (if it was
> enabled)
> on exit, but this 'on exit' is hard to catch...
shopt -s extglob is already done globally and not reverted, doing set +o
posix the same way would not be much worse.
I don't think it's possible to change modes on the fly correctly. If you
do some long operation between set +o posix and set -o posix and ^C
between them then the change will leak to the shell. The only way around
this would be to use a subshell; but you can't write to COMPREPLY from a
subshell. I assume trapping is unacceptable for bash-completion.
But I found a different way around process substitution. It's possible
to pipe a () to a {} and kill the () when you're through with it. I
attached this second variant.
The only problem I found now is that it depends on bash-4 for at least
$BASHPID and read -t with fractional arguments. The fractional timeout
issue makes me think a compatible fix is not worth doing. Bash-3.2 can
still use the blocking implementation. What do you think?
diff --git a/CHANGES b/CHANGES
index 3845158..19a7696 100644
--- a/CHANGES
+++ b/CHANGES
@@ -78,6 +78,7 @@ bash-completion (2.x)
Make it possible to run tests from any directory.
* Add a --debug-xtrace option to test/run using BASH_XTRACEFD from bash-4.1.
* Add a --timeout option to test/run to override the default expect timeout.
+ * Timeout when reading avahi-browse output to avoid hangs (Debian #551780).
[ Raphaƫl Droz ]
* Add xsltproc completion (Alioth: #311843).
diff --git a/bash_completion b/bash_completion
index 41197ac..82fd0a1 100644
--- a/bash_completion
+++ b/bash_completion
@@ -1564,15 +1564,48 @@ _known_hosts_real()
fi
# Add hosts reported by avahi-browse, if it's available.
- # The original call to avahi-browse also had "-k", to avoid lookups into
- # avahi's services DB. We don't need the name of the service, and if it
- # contains ";", it may mistify the result. But on Gentoo (at least),
- # -k isn't available (even if mentioned in the manpage), so...
if type avahi-browse >&/dev/null; then
- COMPREPLY=( "${comprep...@]}" $( \
- compgen -P "$prefix$user" -S "$suffix" -W \
- "$( avahi-browse -cpr _workstation._tcp 2>/dev/null | \
- awk -F';' '/^=/ { print $7 }' | sort -u )" -- "$cur" ) )
+ (
+ # Interactive editing seems to get confused if we kill a nested
+ # process we're also reading from so two nested subshells are # used.
+ #
+ # Don't bite the pipe that's feeding you.
+ echo $BASHPID
+ (
+ echo $BASHPID
+ # The original call to avahi-browse also had "-k", to avoid lookups into
+ # avahi's services DB. We don't need the name of the service, and if it
+ # contains ";", it may mistify the result. But on Gentoo (at least),
+ # -k isn't available (even if mentioned in the manpage), so...
+ avahi-browse -cpr _workstation._tcp 2>/dev/null | \
+ awk -F';' '/^=/ { print $7 }' | sort -u
+ )
+ ) | {
+
+ # Read the pid of the avahi pipe to kill it later.
+ # The processes will die on their own anyway but we don't want to leak
+ # one process every time the users tabs after "ssh "
+ local avahi_pid
+ read -r avahi_ppid
+ read -r avahi_pid
+
+ # Sometimes avahi can take a long time to respond.
+ # If we don't get a response quickly just kill it and move on.
+ local -a avahi_reply
+ while true; do
+ # Read with a timeout.
+ local read_reply read_ret
+ read -rt 0.250 read_reply
+ read_ret=$?
+ [[ $read_ret -gt 128 ]] && kill $avahi_pid
+ [[ $read_ret -ne 0 ]] && break
+ avahi_reply+=("$read_reply")
+ done
+ }
+
+ COMPREPLY=( "${comprep...@]}"
+ $( compgen -P "$prefix$user" -S "$suffix" \
+ -W "${avahi_reply[*]}" -- "$cur" ) )
fi
# Add results of normal hostname completion, unless