Skip site navigation (1)Skip section navigation (2)
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>