Hi,

one my colleague reported me a bug in ksh together with a patch he prepared, 
so I'll just forward it. I was able to reproduce this bug using ksh 2010-03-09 
and attached patch fixed it for me.

Regards,
Michal Hlavinka

--------------------------------------------------------------

Description of problem:
Return of a command substitution from within another command substitution
causes stdin of coprocess to be closed in a ksh script.

Version-Release number of selected component (if applicable):
ksh-20100309-3.fc14.x86_64

How reproducible:
Always

Steps to Reproduce:
1. Execute the following script in ksh:

#######################################
#!/bin/ksh

set -e

co_process()
{
    while read line
    do
    printf "\n%s(): Read line from 'stdin'\n" "${.sh.fun}" >/dev/tty
    done
    printf "\n%s(): Exiting -- EOF on read of 'stdin'.\n" "${.sh.fun}"
>/dev/tty
    # kill the main shell process when the end-of-file is detected on 'stdin'.
    kill $$
}

co_process |&

loop_count=0

while :
do
    (( loop_count++ ))
    printf "%05d: %s\r" "${loop_count}" "$( echo $( /bin/ls ) )"
done 
#######################################

Actual results:

Script ends with the following output:

test_script.ksh: Exiting -- EOF on read of 'stdin'.\n

Expected results:

Script should run in an infinite loop.

Patch:
Close coprocess file descriptors only if the coprocess pid is nonzero

The root cause for this is the race condition between the job_reap called
within the signal handler and job_wait in the parent process. job_reap sets 
the
lastpid to the pid of the process that exited last, so if job_wait is called
after it, it correctly compares a valid pid against the coprocess pid to see 
if
it is the coprocess that has ended.

But in case of a command substitution, the job env (including the coprocess
pid) is backed up and reinitialized, hence making the coprocess pid 0. In this
case, if job_wait happens to execute before job_reap, it compares the 0
coprocess id with the 0 lastpid (since it has not been set through the signal
handler yet) and goes on to close the coprocess assuming that it has quit.

Attached fix ensures that the coprocess pid is actually set before trying to
close its handlers.    
--- a/src/cmd/ksh93/sh/jobs.c	2010-03-10 23:57:41.000000000 +0530
+++ b/src/cmd/ksh93/sh/jobs.c	2010-04-20 18:12:15.000000000 +0530
@@ -1341,7 +1341,7 @@ int	job_wait(register pid_t pid)
 		sfprintf(sfstderr,"ksh: job line %4d: wait pid=%d critical=%d flags=%o\n",__LINE__,getpid(),job.in_critical,pw->p_flag);
 #endif /* DEBUG*/
 	errno = 0;
-	if(sh.coutpipe>=0 && sh.cpid==lastpid)
+	if(sh.coutpipe>=0 && sh.cpid && sh.cpid==lastpid )
 	{
 		sh_close(sh.coutpipe);
 		sh_close(sh.cpipe[1]);
_______________________________________________
ast-developers mailing list
[email protected]
https://mailman.research.att.com/mailman/listinfo/ast-developers

Reply via email to