[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