######################################################################## # # # This software is part of the ast package # # Copyright (c) 1982-2008 AT&T Intellectual Property # # and is licensed under the # # Common Public License, Version 1.0 # # by AT&T Intellectual Property # # # # 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 # # # ######################################################################## # 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<&- wait $! 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++ )) print $to $i $count done while ((count > 0)) do (( count-- )) read -p 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 kill $(jobs -p) 2>/dev/null file=/tmp/regress$$ trap "rm -f $file" EXIT cat > $file <<\! /bin/cat |& ! chmod +x $file sleep 10 |& $file 2> /dev/null || err_exit "parent coprocess prevents script coprocess" exec 5<&p 6>&p exec 5<&- 6>&- kill $(jobs -p) 2>/dev/null ${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>&- wait $! { echo line1 | grep 'line2' echo line2 | grep 'line1' } |& SECONDS=0 count=0 while read -p -t 10 line do ((count++)) done if (( SECONDS > 8 )) then err_exit "read -p hanging (SECONDS=$SECONDS count=$count)" fi wait $! ( sleep 3 |& sleep 1 && kill $!; sleep 1; sleep 3 |& sleep 1 && kill $! ) || err_exit "coprocess cleanup not working correctly" { : |& } 2>/dev/null || err_exit "subshell coprocess lingers in parent" wait $! unset N r e integer N=5 e=12345 ( integer i for ((i = 1; i <= N; i++)) do print $i |& read -p r print -n $r wait $! done print ) 2>/dev/null | read -t 10 r [[ $r == $e ]] || err_exit "coprocess timing bug -- expected $e, got '$r'" r= ( integer i for ((i = 1; i <= N; i++)) do print $i |& sleep 0.01 r=$r$(cat <&p) wait $! done print $r ) 2>/dev/null | read -t 10 r [[ $r == $e ]] || err_exit "coprocess command substitution bug -- expected $e, got '$r'" ( /bin/cat |& sleep 0.01 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 [[ $( { sig=$sig $SHELL 2> /dev/null <<- '++EOF++' cat |& pid=$! trap "print TRAP" $sig ( sleep 2 kill -$sig $$ sleep 2 kill -$sig $$ kill $pid sleep 2 kill $$ ) & read -p ++EOF++ } ) != $'TRAP\nTRAP' ]] 2> /dev/null 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))