[prev in list] [next in list] [prev in thread] [next in thread] 

List:       ast-users
Subject:    [ast-users] safe co-process creation
From:       joe.gainey () odys ! com (Joe Gainey)
Date:       2004-09-03 10:36:29
Message-ID: 41388169.7030508 () odys ! com
[Download RAW message or body]

Cyrille Lefevre wrote:

>"Joe Gainey" <joe.gainey@odys.com> wrote:
>  
>
>>I'm hoping someone has figured out a way around this issue.  I am trying
>>to write a function that can be *safely* called from a users shell
>>script.  The function itself opens up a series of co-processes and does
>>some work.  however, what I have found is that there is no way to safely
>>create a coprocess in my function.  Here's the situation, a user is
>>writing a script that calls my function.  before calling my function the
>>user opens up a coprocess in the user's script.  Then calls my
>>function.  however, because there is already a coprocess opened in the
>>calling script, my function cannot create it's own coprocess.
>>    
>>
>[snip]
>  
>
>>when users run thier script it prints error messages saying "process
>>already exists"
>>    
>>
>
>you have to redirect the file descriptor of the existing co-process before
>to create a new one.
>
>  
>
>>Is there any way around this issue.  Ideally, I would want to be able to
>>use scoped/named pipes instead of a file descriptor numbers. speaking of
>>which what maximum file descriptor number available?  I know some time
>>back I was working on a test harness to do unit testing on an
>>application and had to switch from ksh to perl due to file descriptor
>>issues.
>>    
>>
>
>here is a sample recursive script which open/close co-processes as needed.
>
>integer glob=0 # don't recurse forever
>integer last=3 # last file descriptor used
>function foo {
>        integer count=0 # only print some lines
>
>        ((glob++ == 2)) && return
>        if [[ $1 == redir ]]; then # backup the existing co-process
>                bar="$last<&p"
>                eval exec $bar
>                sleep 1 # wait a moment
>        fi
>        ((last++))
>        cat /etc/passwd |&
>        bar="$last<&p"
>        eval exec $bar
>        while IFS=: read -u$last login passwd uid gid gecos home shell; do
>                [[ $login == root ]] && foo noredir
>                print $last: $login $passwd $uid $gid $gecos $home $shell
>                ((count++ == 5)) && break
>        done
>        bar="$last<&-"
>        eval exec $bar
>        # sleep 1 # maybe needed under ksh88
>        wait $!
>        ((last--))
>}
># typeset -ft foo; set -x
>cat /etc/passwd |&
>foo redir
>IFS=: read -u$last login passwd uid gid gecos home shell
>print $last: $login $passwd $uid $gid $gecos $home $shell
>
>however, ksh93 is broken in three way :
>- exec $var<&p doesn't work as is ! the following construction is needed :
>    bar="$var<&p"; eval exec $bar
>- you have to wait some time between a co-process redirection and a co-process
>creation (aka, sleep 1) !
>- if seems you can't redirect a file descriptor to a newer one which is greater
>or equal to 10, in other words, you are limited to one digit file descriptors !
>ks88 doesn't allow you to fork more than one co-process at a time, even with
>redirections :(
>also, in ksh88, between a co-process close and a co-process wait, you may need
>to wait some time too (sleep 1), don't know if this is needed under ksh93 ?
>
>PS : if you try to redirect a non-existing co-process, you are dead. this
>behaviour could be considered as normal (aka, exec 3<&p w/o a preceding ...
>|& ).
>also, you can't restore a co-process once redirected (aka, exec p<&3).
>
>Cyrille Lefevre.
>  
>
Thanks for the feedback.  you are correct, there are two things that I 
can't fix.  The first is that ksh is limited to only a few number of 
file descriptors.  this makes it difficult to write a function that 
executes multiple jobs asynchronously (for example think about writing 
cron is ksh).  The second is that assuming there is a way to detect when 
a calling script has created a co-process, there is no way to redirect 
the calling co-process to new file descriptors and then redirect it back 
again. 

of course if I am writing  *library* functions for users to call I don't 
think it is appropriate for my library to redirect i/o from user 
co-proceses to a different file descriptor than the one they are using 
without returning it back to the way it was.  The whole point of a 
library is that it is something that just exists, works, and users don't 
have to worry about the internal workings of it.  It seems that with ksh 
writing a library is difficult to do especially if your library uses 
co-processes.

You are correct if you try to redirect a co-process that doesn't exist 
you will have a problem, and you cannot restore a co-process to the way 
it was once it was redirected (or can you fd0, fd1, fd2?).    There 
should either be a way to determine what file descriptors are in use, or 
you should be able to create a co-process and arbitrarily assign the 
file descriptors for that co-process at the time it is created.  Maybe, 
the shell should provide  /*.sh*/ variable that contains those file 
descriptors so they can be assigned to arbitrary variables. maybe 
something like:

typeset -A FD
/command  /*|+*
FD[0]=${.sh.coproc[stdin]}
FD[1]=${.sh.coproc[stdout]}
FD[2]=${.sh.coproc[stderr]}

Notice that I used *|+ *instead of *|&* to denote a different type of 
coproc.  I really don't know how you would implement this while 
maintaining backwards compatibility.  But it would be a nice feature to 
have the ability to write a library function that people could use 
without knowing any of the internals of the function.

*
*
Joe

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic