On Sun, Nov 04, 2007 at 09:37:52PM -0800, Scott Lamb <[EMAIL PROTECTED]> wrote:
> > There is actually a lot of code that relies on this just working, and the
> > only other event loop I know that has a problem with this is Tk.
> Ugh, I'd argue that idiom is broken. But if the support's free, I guess
> it doesn't matter.

Well, the idiom is how it works in most languages nowadays, so wether broken
or not its important to support.

The main problem is that with the current libevent implementation, failures
are completely silent.

> >>>   as is required for integration of other event-based libraries, without
> >>>   having to force the use of some construct around event_loop.
> > 
> > I don't udnerstand that, there is no construct around event_loop, its 
> > handled
> > completely seperately.
> My question was in response to your "I added idle watchers, pid watchers

Ah, now I get it :)

Well, it requires a construct around event_loop because there is no way to
hook into event_loop. Of course, if you have those watcher type you don't
need anything around your loop call. Sorry if that was worded confusingly.

> > This is true, but its an optional feature you don't have to use.  In case
> > you wonder, EV, the perl interface to libev, uses this feature.
> > 
> > It makes most sense when embedding, of course (not all the world is an .so
> > :).
> Hmm, in your Perl example, I wouldn't rule out you wanting to share the
> event loop with some C-based library and being unable to do so.

If you want to share it, you of course cannot do that unless that c-based
library uses the same version of the code.

But this is in no way difefrent to libevent: if one program links it
statically and other shared, or if one program uses 1.3d and another 1.3e
(different sonames), then you can't share it either.

> There's definitely nothing you can't do with a void*, so this is all a
> question of efficiency.

Its also a question of coding overhead, which is probably more important than
efficiency in this case.

Especially as efficieny is a red herring. in the libev proposed api,
callbacks get the watcher object passed, which

a) is often what you want anyways
b) is allocated by user code, so you cna just make the struct larger
   by appending your data.

this solves the efficiency issue and also makes for a simpler API.

In fact, I pondered long on wether I even add a void *arg to each event
watcher, but I thought the overhead of havign to "subclass" is large in the
common case where a single pointer indeed is enough.

In any case, let me repeat that this is an optional feature, not a
limitation, in the API.

> I assert that the cost of a sizeof(void*) to
> point to the relevant part of your structure (which can be
> nearby...still reasonable cache locality) is not too high.

Its higher than necessary, and more complex than neccessary.

> > All callbacks will be called with EV_ERROR when an error occurs. And yes,
> > if you don't do error handlign and endlessly retry the same operation in a
> > loop, you run into problems.
> > 
> > But as that is an obvious programming bug, I don't see any problem here.
> Hmm. Let me introduce a use case: an event-driven program which must not
> fail. init or similar.
> I worked on such a program recently. If it were unreliable, you would
> have to send the system back to the factory for repair (i.e., flashing
> new software). On ENOMEM, it would basically sleep and retry. This was
> quite successful (memory could be temporarily consumed by network
> buffers, etc, which cleared itself up after a while).

This could be solved easier with having a generic callback thats called in
such special conditions.

The alternative to have every event_add etc. call surrounded by checking
code is not realistic, especially if some of the code is not easily
changable (such as the libevent code itself which doesn't check for such

> For this program, it's important to know more than that an error has
> occurred. EV_ERROR is totally inadequate.

You already know more: you know which watcher caused it, or which watcher is

> What is my program supposed to do? It can't distinguish them, and the
> correct behavior in each of these conditions is totally different. Also,
> in the program I'm thinking of, "libev chose to kill this file
> descriptor" probably means a network link just went down. Ergh.

killing the file descriptor might indeed be harsh. all that libev does now is
stop the event watcher and signal an error.

> > Besides, if you cannot malloc the few bytes ev_once requires you need a
> > *lot* of good error handlign code to continue sensibly.
> Yes, as I've mentioned above, there are programs for which this level of
> error handling is necessary.

I agree, but libevent already doesn't provide this, so its moot to compare
this case to libevent. However, it would be very interetsing to actualyl talk
about an API that solves this problem.

For example, on ENOMEM, one could have a callback thats called, because I cna
imagine that sleeping is a common situation.

However, for select, its quite likely that sleepign will not help ever,
so your example init program would simply freeze, as it cna reattempt the
select as many times as it wants but it won't change because many osses
issue enomem not just in response to real memory shortness but simply when
the number of fds grows high (in fact, its usually the only case where
this happens).

The default action could be to stop some watchers, while a callback might
decide to do something else.

What kind of error callbacks would you think are necessary?

I would identify the same cases we already have (fd_enomem, fd_badf) and
additionally enomem for any malloc-type error.

The event watcher would be signalled in any case, and the callback can decide
wether to use the default action or do its own stuff.

Would that be better?

> > If the app cannot handle that, deep shit.
> There are applications which can handle you returning ENOMEM to them on
> select(), but basically no applications which can reliably handle you
> randomly closing their file descriptors.

Ok, what will they do if the problem in select is that fd numbers used
wree too high? How can this sensibly be handled other than by aborting
and, say, restarting?

> * any X11 application is screwed if you close its connection to the server

Uhm, no? :)

> * any server is going to assume nothing will happen to its listen socket

For realistic cases the listen socket won't be affected by enomem as it has a
lower number than the fds causing the problem.

And in the case of ebadf, well, your listen socket is already gone
anyways, no harm done.

> > In any case, you can get the same behaviour as libevent by calling unloop
> > in case of an error, so the interface is strictly more powerful.
> No, on error your library may have muddied the water already by screwing
> with the file descriptors. libevent also makes errors clearer by simply
> returning error from the failed function (I'm thinking of event_once()
> vs ev_once() here.)

I wrote about this in my other mail.

> > I do think the design is useful in practise, where error handling is rarely
> > done to the utmost extent and sensible behaviour in dead-end situations
> > counts a lot.
> There are a lot of sucky programs out there, but I think it's important
> to not penalize the ones where it counts the most.

I don't think one should penalise most programs when a few programs can
still do what they need. I folow the motto "simple things should be
simple, complicated ones possible" - complicating error handlign for
everybody because a few rare apps might actually simplify is not a good

> Many servers; on Linux, the NFS daemons; etc

Uhm, I somehow doubt that the kernel uses libevent internally (and the
kernel is where the nfs daemons are).

(There are userspace nfs daemons, but even if they use libevent, they are
far more broken and fragile than the standard nfs daemons in linux).

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      [EMAIL PROTECTED]
      -=====/_/_//_/\_,_/ /_/\_\
Libevent-users mailing list

Reply via email to