Date: Mon, 31 Mar 2008 21:45:38 +0200 From: Mel <fbsd.hackers@rachie.is-a-geek.net> To: Dag-Erling =?utf-8?q?Sm=C3=B8rgrav?= <des@des.no> Cc: freebsd-hackers@freebsd.org Subject: Re: Popen and EVFILT_WRITE question Message-ID: <200803312145.39372.fbsd.hackers@rachie.is-a-geek.net> In-Reply-To: <86ve33wo1e.fsf@ds4.des.no> References: <200803301220.39921.fbsd.hackers@rachie.is-a-geek.net> <86ve33wo1e.fsf@ds4.des.no>
next in thread | previous in thread | raw e-mail | index | archive | help
On Monday 31 March 2008 05:49:33 Dag-Erling Sm=C3=B8rgrav wrote: > Mel <fbsd.hackers@rachie.is-a-geek.net> writes: > > Hi, > > > > from reading the manpage on EVFILT_WRITE I thought it would be an easy = to > > use interface to detect when a program wants input. > > So far, that doesn't seem to be the case. Ultimately what I want to do = is > > pipe all the popen(3)'d output to a logfile and act on any input it > > wants. > > > > Could anyone explain to me why I'm never getting the EVFILT_WRITE event > > in below testcode? > > (It doesn't matter if I open the pipe with w+ or r+). > > > > test.c: > > #include <sys/types.h> > > #include <sys/event.h> > > #include <sys/time.h> > > #include <sysexits.h> > > #include <err.h> > > #include <stdio.h> > > > > int main(int argc, char **argv) > > { > > FILE *proc; > > int kq; > > struct kevent changes[2], events[2]; > > > > proc =3D popen("./test.sh", "w+"); > > if( -1 =3D=3D (kq =3D kqueue()) ) > > err(EX_OSERR, "Cannot get a kqueue"); > > > > EV_SET(&changes[0], fileno(proc), EVFILT_WRITE, EV_ADD|EV_ENABLE, 0, > > 0, 0); > > EV_SET(&changes[1], fileno(proc), EVFILT_READ, EV_ADD|EV_ENABLE, 0, > > 0, 0); > > This is never going to work. > > First, the second kevent overrides the first, because they both have the > same ident. No, the ident is one part of the uniqueness. The filter type is the second. > Third, an EVFILT_WRITE event will trigger as long as there is space in > the pipe buffer. > There is no such thing as "when a program wants input"=20 > in Unix; Yeah, I figured that out. Still, the write never fires and that seems like = a=20 bug to me, cause it should fire since there's space in the buffer. In fact,= =20 if you fill the buffer partially before going into the event loop, it does= =20 fire each loop. Plan was to use trickery like fill the buffer up to PIPE_SIZE and when it's= =20 drained means the child read the input and we should fill it again. Then I saw the various pipe sizes and didn't think it would be a good idea,= so=20 went with a timeout of 'no input received' instead. > it will either read input or it won't, and what happens when it=20 > reads depends entirely on what the fd it reads from is connected to, > whether it's a slow or fast device, blocking or non-blocking, etc. The kernel knows that the fd at the end of the pipe is blocked for reading.= =20 Does it also know it's the end of a pipe and what's on the other end? Cause= =20 it would be a cool filter to have, if you could detect a blocked child as a= =20 parent. It sure is better then arbitrary timeouts (this code will run 'make= =20 install' as a daemon(3) and write 'yes' on those nasty post-install questio= ns=20 in ports). =2D-=20 Mel
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803312145.39372.fbsd.hackers>