Re: [Libevent-users] EV_PERSIST behavior

2007-05-08 Thread Christopher Layne
On Tue, May 08, 2007 at 06:38:51PM -0700, William Ahern wrote:
> > received a non-timeout event. In a way this is absolute, not in the epoch
> > sense, but that it's tied to the time event_add() was called and not 
> > relative
> > to when the last valid event was received.
> 
> That may or may not make sense the majority of the time.
> 
> Most of the time you're reading logical data atoms, not bytes.
> 
> Say you set a timeout for 10 seconds, but a socket polled as ready once
> every 9 seconds. Maybe there's a single byte available, maybe there's none
> (because the event notification was spurious). You're line buffering, and
> maybe you've set an upper bound on line length of 1000 bytes (e.g. SMTP).
> 
> You could be polling for almost 3 hours if the peer trickled data
> byte-by-byte. If the peer was exceptionally smart, he could keep the
> connection open forever, by sending malformed packets which set the socket
> state as ready but were subsequently discarded further down the TCP stack.

Sure, but this is already way higher level than libevent would be concerned
with. Additionally it's easily (relatively) handled by keeping track of the
exceptional states and reacting against it.

Besides, libevent has no notion of completion or even a way to provide that by
a particular metric or count. It's concerned with readiness about the most
basic level.

If an event is fired, the timeout should be implicitly reset to 0, awaiting
either the next valid event to reset the timeout again or a timeout itself for
which to make the timeout event valid in the first place.

-cl
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] EV_PERSIST behavior

2007-05-08 Thread William Ahern
On Tue, May 08, 2007 at 06:10:29PM -0700, Christopher Layne wrote:
> On Tue, May 08, 2007 at 02:03:17PM -0700, Niels Provos wrote:
> > On 5/8/07, Phil Oleson <[EMAIL PROTECTED]> wrote:
> > >So..  To fix your implementation you will need to do something like I did.
> > >I reimplemented libevents' gettime() function (because it's not exposed
> > >via event.h) and use it instead of calling time(NULL);
> > 
> > I don't really understand why you are saying that.  Timeouts are
> > incremental and not in absolute time.  So, you don't really need to
> > understand anything about the underlying implementation.
> 
> To me, it seems like the timeouts do not reset on an EV_PERSIST event that
> received a non-timeout event. In a way this is absolute, not in the epoch
> sense, but that it's tied to the time event_add() was called and not relative
> to when the last valid event was received.

That may or may not make sense the majority of the time.

Most of the time you're reading logical data atoms, not bytes.

Say you set a timeout for 10 seconds, but a socket polled as ready once
every 9 seconds. Maybe there's a single byte available, maybe there's none
(because the event notification was spurious). You're line buffering, and
maybe you've set an upper bound on line length of 1000 bytes (e.g. SMTP).

You could be polling for almost 3 hours if the peer trickled data
byte-by-byte. If the peer was exceptionally smart, he could keep the
connection open forever, by sending malformed packets which set the socket
state as ready but were subsequently discarded further down the TCP stack.

___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] EV_PERSIST behavior

2007-05-08 Thread Christopher Layne
On Tue, May 08, 2007 at 02:03:17PM -0700, Niels Provos wrote:
> On 5/8/07, Phil Oleson <[EMAIL PROTECTED]> wrote:
> >So..  To fix your implementation you will need to do something like I did.
> >I reimplemented libevents' gettime() function (because it's not exposed
> >via event.h) and use it instead of calling time(NULL);
> 
> I don't really understand why you are saying that.  Timeouts are
> incremental and not in absolute time.  So, you don't really need to
> understand anything about the underlying implementation.

To me, it seems like the timeouts do not reset on an EV_PERSIST event that
received a non-timeout event. In a way this is absolute, not in the epoch
sense, but that it's tied to the time event_add() was called and not relative
to when the last valid event was received.

-cl
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] EV_PERSIST behavior

2007-05-08 Thread Niels Provos

On 5/8/07, Phil Oleson <[EMAIL PROTECTED]> wrote:

So..  To fix your implementation you will need to do something like I did.
I reimplemented libevents' gettime() function (because it's not exposed
via event.h) and use it instead of calling time(NULL);


I don't really understand why you are saying that.  Timeouts are
incremental and not in absolute time.  So, you don't really need to
understand anything about the underlying implementation.

Niels.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


Re: [Libevent-users] EV_PERSIST behavior

2007-05-08 Thread Phil Oleson

Christopher Layne wrote:

I understand that EV_PERSIST basically means that one does not have to
continually reschedule the event upon the event occuring.

Consider the following simple test case and my following question on it...




Documentation for that is here:
 The function event_add() schedules the execution of the ev event when
 the event specified in event_set() occurs or in at least the time speci-
 fied in the tv.  If tv is NULL, no timeout occurs and the function
 will only be called if a matching event occurs on the file descriptor.
 The event in the ev argument must be already initialized by event_set()
 and may not be used in calls to event_set() until it has timed out or
   implies event_del() -->   ^
 been removed with event_del().  If the event in the ev argument already
 has a scheduled timeout, the old timeout will be replaced by the new one.

Just took a bit to find it in the manpage. It might want to be more explictly
stated in the documentation.


Well, I've dealt with this before, so I'll give you the rundown.
libevent uses clock_gettime() and CLOCK_MONOTONIC within it's queues
to keep events happening across time changes on the system.

So..  To fix your implementation you will need to do something like I did.
I reimplemented libevents' gettime() function (because it's not exposed
via event.h) and use it instead of calling time(NULL);

-Phil.
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users


[Libevent-users] EV_PERSIST behavior

2007-05-08 Thread Christopher Layne
I understand that EV_PERSIST basically means that one does not have to
continually reschedule the event upon the event occuring.

Consider the following simple test case and my following question on it...

#include 
#include 
#include 
#include 
#include 
#include 

int pfd[2];
int persist[2];
struct event e;

void rp(int fd, short event, void *p)
{
struct timeval tv = { 4, 0 };
time_t tn, *t = p;
char c;

tn = time(NULL);
fprintf(stderr, "event callback, tdiff == %lu\n", tn - *t);

if (event == EV_TIMEOUT) {
fprintf(stderr, "timeout\n");
if (!persist[1])
event_add(&e, &tv);

return;
} else if (!persist[0]) {
event_add(&e, &tv);
}

read(fd, &c, 1);
fprintf(stderr, "writing to pipe\n");
write(pfd[1], ".", 1);
sleep(1);

return;
}

int main(int argc, char **argv)
{
struct timeval tv = { 4, 0 };
time_t t = time(NULL);

pipe(pfd);
write(pfd[1], ".", 1);
persist[0] = argc > 1 ? EV_PERSIST : 0;
persist[1] = argc > 2 ? 1 : 0;

event_init();
event_set(&e, pfd[0], EV_READ | persist[0], rp, &t);
event_add(&e, &tv);
event_dispatch();

return 0;
}

$ gcc -o evs evs.c -levent

1. Here, we schedule an event and continually reschedule it upon the event
firing. No timeout ever occurs because we are writing to the pipe every
second. This seems like intuitive and normal behavior to me, with regards
to timeouts (they never occur because we're writing):

$ ./evs
event callback, tdiff == 0
writing to pipe
event callback, tdiff == 1
writing to pipe
event callback, tdiff == 2
writing to pipe
event callback, tdiff == 3
writing to pipe
event callback, tdiff == 4
writing to pipe
event callback, tdiff == 5
writing to pipe
event callback, tdiff == 6
writing to pipe
^C

2. Here, we set EV_PERSIST, write an initial byte and then write to the
pipe just like the previous example. However the part that seems entirely
unintuitive to me is that a timeout event is being fired almost as if the
timeout was based on absolute time. I would think that it would be expected
behavior that if one were to set a timeout with event_set(), the timeout
will only be fired if the event does not occur within the specified timeout
period - just as if you were to be doing a typical "tv.tv_sec = tout; ret =
select(..., &tv);" loop. But that idiom is not what is followed when using
EV_PERSIST. The timeout occurs anyways, even if a read event is continuously
being fired. What am I missing here?

$ ./evs p
event callback, tdiff == 0
writing to pipe
event callback, tdiff == 1
writing to pipe
event callback, tdiff == 2
writing to pipe
event callback, tdiff == 3
writing to pipe
event callback, tdiff == 4
timeout
event callback, tdiff == 4
writing to pipe
event callback, tdiff == 5
writing to pipe
event callback, tdiff == 6
writing to pipe
event callback, tdiff == 7
writing to pipe
event callback, tdiff == 8
timeout
event callback, tdiff == 8
writing to pipe
event callback, tdiff == 9
writing to pipe
^C

3. event_dispatch() will return if we do not reschedule the event after a
timeout occurs, even with EV_PERSIST. I don't have any issue with this,
but it did surprise me when I first started using the library.

$ ./evs p p
event callback, tdiff == 0
writing to pipe
event callback, tdiff == 1
writing to pipe
event callback, tdiff == 2
writing to pipe
event callback, tdiff == 3
writing to pipe
event callback, tdiff == 4
timeout
$

Documentation for that is here:
 The function event_add() schedules the execution of the ev event when
 the event specified in event_set() occurs or in at least the time speci-
 fied in the tv.  If tv is NULL, no timeout occurs and the function
 will only be called if a matching event occurs on the file descriptor.
 The event in the ev argument must be already initialized by event_set()
 and may not be used in calls to event_set() until it has timed out or
   implies event_del() -->   ^
 been removed with event_del().  If the event in the ev argument already
 has a scheduled timeout, the old timeout will be replaced by the new one.

Just took a bit to find it in the manpage. It might want to be more explictly
stated in the documentation.

-cl
___
Libevent-users mailing list
Libevent-users@monkey.org
http://monkey.org/mailman/listinfo/libevent-users