coprocess.sh revision da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968
########################################################################
# #
# This software is part of the ast package #
# Copyright (c) 1982-2007 AT&T Knowledge Ventures #
# and is licensed under the #
# Common Public License, Version 1.0 #
# by AT&T Knowledge Ventures #
# #
# A copy of the License is available at #
# http://www.opensource.org/licenses/cpl1.0.txt #
# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) #
# #
# Information and Software Systems Research #
# AT&T Research #
# Florham Park NJ #
# #
# David Korn <dgk@research.att.com> #
# #
########################################################################
# test the behavior of co-processes
function err_exit
{
print -u2 -n "\t"
print -u2 -r ${Command}[$1]: "${@:2}"
let Errors+=1
}
alias err_exit='err_exit $LINENO'
Command=${0##*/}
integer Errors=0
if [[ -d /cygdrive ]]
then err_exit cygwin detected - coprocess tests disabled - enable at the risk of wedging your system
exit $((Errors))
fi
function ping # id
{
integer x=0
while ((x < 5))
do read -r
print -r "$1 $REPLY"
done
}
cat |&
print -p "hello"
read -p line
[[ $line == hello ]] || err_exit 'coprocessing fails'
exec 5>&p 6<&p
print -u5 'hello again' || err_exit 'write on u5 fails'
read -u6 line
[[ $line == 'hello again' ]] || err_exit 'coprocess after moving fds fails'
exec 5<&- 6<&-
ping three |&
exec 3>&p
ping four |&
exec 4>&p
ping pipe |&
integer count
for i in three four pipe four pipe four three pipe pipe three pipe
do case $i in
three) to=-u3;;
four) to=-u4;;
pipe) to=-p;;
esac
count=count+1
print $to $i $count
done
while ((count > 0))
do count=count-1
read -p
# print -r - "$REPLY"
set -- $REPLY
if [[ $1 != $2 ]]
then err_exit "$1 does not match 2"
fi
case $1 in
three);;
four) ;;
pipe) ;;
*) err_exit "unknown message +|$REPLY|+"
esac
done
file=/tmp/regress$$
trap "rm -f $file" EXIT
cat > $file <<\!
/bin/cat |&
!
chmod +x $file
$file 2> /dev/null || err_exit "parent coprocess prevents script coprocess"
exec 5<&p 6>&p
exec 5<&- 6>&-
${SHELL-ksh} |&
print -p $'print hello | cat\nprint Done'
read -t 5 -p
read -t 5 -p
if [[ $REPLY != Done ]]
then err_exit "${SHELL-ksh} coprocess not working"
fi
exec 5<&p 6>&p
exec 5<&- 6>&-
count=0
{
echo line1 | grep 'line2'
echo line2 | grep 'line1'
} |&
SECONDS=0
while
read -p -t 10 line
do
((count = count + 1))
echo "Line $count: $line"
done
if (( SECONDS > 8 ))
then err_exit 'read -p hanging'
fi
( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) ||
err_exit "coprocess cleanup not working correctly"
unset line
(
integer n=0
while read line
do echo $line |&
if cat <&p
then ((n++))
wait $!
fi
done > /dev/null 2>&1 <<- !
line1
line2
line3
line4
line5
line6
line7
!
(( n==7 )) && print ok
) | read -t 10 line
if [[ $line != ok ]]
then err_exit 'coprocess timing bug'
fi
(
/bin/cat |&
exec 6>&p
print -u6 ok
exec 6>&-
sleep 1
kill $! 2> /dev/null
) && err_exit 'coprocess with subshell would hang'
for sig in IOT ABRT
do if ( trap - $sig ) 2> /dev/null
then if [[ $(
cat |&
pid=$!
trap "print TRAP" $sig
(
sleep 2
kill -$sig $$
sleep 2
kill -$sig $$
kill $pid
) 2> /dev/null &
read -p
) != $'TRAP\nTRAP' ]]
then err_exit 'traps when reading from coprocess not working'
fi
break
fi
done
trap 'sleep_pid=; kill $pid; err_exit "coprocess 1 hung"' TERM
{ sleep 5; kill $$; } &
sleep_pid=$!
builtin cat
cat |&
pid=$!
exec 5<&p 6>&p
print -u6 hi; read -u5
[[ $REPLY == hi ]] || err_exit 'REPLY is $REPLY not hi'
exec 6>&-
wait $pid
trap - TERM
[[ $sleep_pid ]] && kill $sleep_pid
trap 'sleep_pid=; kill $pid; err_exit "coprocess 2 hung"' TERM
{ sleep 5; kill $$; } &
sleep_pid=$!
cat |&
pid=$!
print foo >&p 2> /dev/null || err_exit 'first write of foo to coprocess failed'
print foo >&p 2> /dev/null || err_exit 'second write of foo to coprocess failed'
kill $pid
wait $pid 2> /dev/null
trap - TERM
[[ $sleep_pid ]] && kill $sleep_pid
trap 'sleep_pid=; kill $pid; err_exit "coprocess 3 hung"' TERM
{ sleep 5; kill $$; } &
sleep_pid=$!
cat |&
pid=$!
print -p foo
print -p bar
read <&p || err_exit 'first read from coprocess failed'
[[ $REPLY == foo ]] || err_exit "first REPLY is $REPLY not foo"
read <&p || err_exit 'second read from coprocess failed'
[[ $REPLY == bar ]] || err_exit "second REPLY is $REPLY not bar"
kill $pid
wait $pid 2> /dev/null
trap - TERM
[[ $sleep_pid ]] && kill $sleep_pid
exit $((Errors))