Bug 157013

Summary: Bizarre file descriptor race condition
Product: Base System Reporter: Aragon Gouveia <aragon>
Component: binAssignee: Jilles Tjoelker <jilles>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 8.2-STABLE   
Hardware: Any   
OS: Any   

Description Aragon Gouveia 2011-05-13 20:20:10 UTC
Please see the script pasted in the repeat field.

When it is run, the while loop exits after the first iteration.  However,
if the ssh command is commented, the loop executes two iterations.

Stranger still, on some of my FreeBSD systems the script works correctly
_sometimes_, but mostly not.

How-To-Repeat: #!/bin/sh

DFRTMP=$(mktemp -d /tmp/dfr.XXXXXX)
[ $? -eq 0 ] || exit 1

cat >${DFRTMP}/hosts <<"_EOF"
1 saturn.geek.sh
2 null
_EOF

while read hostid hostname; do
        echo ${hostid}:${hostname}
        ssh ${hostname} 'df -k'
done <${DFRTMP}/hosts

rm -rf ${DFRTMP}
Comment 1 Jilles Tjoelker freebsd_committer freebsd_triage 2011-05-14 00:18:18 UTC
State Changed
From-To: open->closed

This is not a bug but a fairly common caveat with ssh(1). 

The problem is that ssh(1) does not know if the other side wants 
input and therefore it reads data and sends it to the other side. 
Once data has been read from a pipe there is no way to put it back. 
It would be possible with a regular file but determining the amount 
to put back would be very complicated and unreliable. 

If the other side is very fast, it might finish executing the 
command before ssh(1) attempts its first read and the script 
might work as intended. 

You can solve the problem by redirecting ssh's input (either with 
shell redirection or with the -n option) or by using a different 
file descriptor for the list, like: 

while read hostid hostname <&3; do 
echo ${hostid}:${hostname} 
ssh ${hostname} 'df -k' 
done 3<${DFRTMP}/hosts 


Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2011-05-14 00:18:18 UTC
Responsible Changed
From-To: freebsd-bugs->jilles

Track.