Wow.  What a strange circumstance.  That must have been somewhat
puzzling to debug.  Your fix seems fine although - I think - it might
not be sufficient.  I don't think that anybody (but me and maybe a
couple who read the source code) even know about the high-water mark
feature.

Perhaps there should be a limit by how much a buffer can be increased
at any given time?
Thank you very much for figuring this out,

Niels.

Cc'ing libevent users for more feedback.

On 2/4/06, Christopher Maxwell <[EMAIL PROTECTED]> wrote:
> It has taken quite a strange set of circumstances to do this, but I have
> discovered a new way to exhaust system memory when trying to read from a
> bufferevent.
>
> After externally copying a large file to another filesystem, such that a
> very large portion of the file remains in the system buffer cache (UBC?),
> the automatic calculation by bufferevent_readcb() and evbuffer_read()
> notices the absurdly large number of bytes immediately available to read and
> attempts to resize the evbuffer.  This all happens before any callbacks can
> be run to drain the evbuffer.  In my case, a file of ~100MB appeared all at
> once, was packaged into another 100MB outbound buffer, then promptly
> exploded.
>
> I could not find any knobs to adjust as watermarks are not checked until
> long after the buffer read.  Below is a patch to bufferevent_readcb() that
> constrains the read size to the high watermark, if set.  The plan is to
> give the application a fighting chance to drain the buffer, or at least
> disable it for a time if it cannot.
>
> cheers
> --chris
> [EMAIL PROTECTED]
>
> --- evbuffer.c.orig     Sun Feb  5 00:21:06 2006
> +++ evbuffer.c  Sun Feb  5 00:20:45 2006
> @@ -92,13 +92,17 @@
>         int res = 0;
>         short what = EVBUFFER_READ;
>         size_t len;
> +       int howmuch = -1;
>
>         if (event == EV_TIMEOUT) {
>                 what |= EVBUFFER_TIMEOUT;
>                 goto error;
>         }
>
> -       res = evbuffer_read(bufev->input, fd, -1);
> +       if (bufev->wm_read.high != 0)
> +               howmuch = bufev->wm_read.high;
> +
> +       res = evbuffer_read(bufev->input, fd, howmuch);
>         if (res == -1) {
>                 if (errno == EAGAIN || errno == EINTR)
>                         goto reschedule;
>
>
_______________________________________________
Libevent-users mailing list
[email protected]
http://monkey.org/mailman/listinfo/libevent-users

Reply via email to