[prev in list] [next in list] [prev in thread] [next in thread]
List: opensolaris-code
Subject: Re: [osol-code] |poll()| on multiple FIFOs vs. partial reads
From: Roland Mainz <roland.mainz () nrubsig ! org>
Date: 2007-10-18 7:12:18
Message-ID: 47170752.A4BE0E81 () nrubsig ! org
[Download RAW message or body]
Hi!
----
[CC:'ing Andreas Borchert since he did a quick look at the problem]
Garrett D'Amore wrote:
> Roland Mainz wrote:
> > I'm currently writing a small application which should use |poll()| on
> > multiple FIFOs (created via /usr/bin/mkfifo) - after some testing I hit
> > a weired behaviour: The FIFOs are fed from other processes (one FIFO per
> > process) which never terminate (e.g. |POLLHUP| not involved) and only
> > write data from time to time into the FIFOs and the consumer application
> > uses |poll()| to wait for incoming data. It seems that if the consumer
> > only reads some data from a FIFO file descriptor and not all queued data
> > then the |revent| field for this pollfd entry will return |0| on the
> > following |poll()| call (even if there are still data queued).
> > Is this the correct behaviour ?
>
> That certainly doesn't *sound* correct. It *sounds* like a bug to me.
>
> POLLIN Data other than high priority data may be read
> without blocking. For STREAMS, this flag is set
> in revents even if the message is of zero
> length.
>
> The description above doesn't indicate anything about whether the data
> had previously been signaled or not.
>
> That said, it does seem strange that you would read less than the full
> amount of data available in the FIFO at any given time.
The idea is to have a script which executes something like "tail -f" on
_multiple_ files and read one line per watched file in a round-robin
fashion if multiple files provide data.
For example the follwing script:
-- snip --
function fatal_error
{
print -u 2 "${progname}: $@"
exit 1
}
function usage
{
OPTIND=0
getopts -a "${progname}" "${USAGE}" OPT '-?'
exit 2
}
# program start
builtin basename
builtin cat
typeset progname="$(basename "${0}")"
USAGE=$'
[-?\n@(#)\$Id: multifollow (Roland Mainz) 2007-10-09 \$\n]
[-author?Roland Mainz <roland.mainz@nrubsig.org]
[+NAME?multifollow - use tail -f on multiple files]
[+DESCRIPTION?\bmultifollow\b is a small utilty which can "follow"
multiple
files similar to tail -f.]
[ file ... ]
[+SEE ALSO?\bksh93\b(1), \btail\b(1)]
'
while getopts -a "${progname}" "${USAGE}" OPT ; do
# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
case ${OPT} in
*) usage ;;
esac
done
shift $((OPTIND-1))
# expecting at least one more arguments
(($# >= 1)) || usage
builtin -f libshell.so.1 poll || fatal_error "poll builtin not found."
typeset -a files
integer numfiles=0
integer i
# register trap to cleanup child processes
trap 'for ((i=0 ; i < numfiles ; i++ )) ; do kill -TERM
${files[i].childpid} ; done' EXIT
while (($# > 0)) ; do
typeset files[${numfiles}]=(
typeset name="$1"
typeset pipename="/tmp/multifollow_pipe_${PPID}_$$_${numfiles}"
integer childpid=-1
# poll(1) information
integer fd="-1"
typeset events="POLLIN|POLLRDNORM|POLLRDBAND|POLLPRI"
typeset revents=""
)
mkfifo "${files[${numfiles}].pipename}"
exec {files[numfiles].fd}<>"${files[numfiles].pipename}"
tail -f "${files[${numfiles}].name}"
>"${files[${numfiles}].pipename}" &
files[${numfiles}].childpid=$!
rm "${files[${numfiles}].pipename}"
shift
(( numfiles++ ))
done
typeset do_poll=true
while true ; do
if ${do_poll} ; then
for ((i=0 ; i < numfiles ; i++ )) ; do
files[i].revents=""
done
poll files
fi
do_poll=true
for ((i=0 ; i < numfiles ; i++ )) ; do
if [[ "${files[i].revents}" != "" ]] ; then
# todo: investigate why we have to use "do_poll" at all - AFAIK it
# should be sufficient to call "poll" and get "revents" set if
there
# are any remaining data...
if read -t0 -u${files[i].fd} line ; then
print -- "#${i}: ${line}"
do_poll=false
fi
fi
done
done
fatal_error "not reached."
# EOF.
-- snip --
... uses "poll" to watch multiple FIFOs... but strangely I have to use
the "do_poll"-hack (see comment in the code) ... and even stranger
(OkOk, not exactly a suprise): Commenting the "do_poll=false"-line out
results in something like this:
-- snip --
$ ksh93 multifollow.ksh /var/adm/messages /var/log/syslog
#0: Oct 18 07:53:43 sxb72x86 genunix: [ID 936769 kern.info] dtrace0 is
/pseudo/dtrace@0
#1: Oct 13 04:03:27 sxb72x86 sendmail[391]: [ID 702911 mail.info]
starting daemon (8.14.1+Sun): queueing@00:15:00
poll: poll: failure [Interrupted system call]
-- snip --
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz@nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 7950090
(;O/ \/ \O;)
_______________________________________________
opensolaris-code mailing list
opensolaris-code@opensolaris.org
http://mail.opensolaris.org/mailman/listinfo/opensolaris-code
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic