Testing the patch a bit more thoroughly, I managed to find a case where the
buffer grows beyond the high watermark, and deadlocks -  bufferevent_readcb()
has a check for high watermark that returns without allowing the user callback
to run.  Simply removing the return from the end of the high watermark check
repairs this - but I am unsure whether this affects the expected behaviour
for the high watermark.

below is the total patch to date
--chris

--- evbuffer.c.orig     Tue Apr 19 18:55:45 2005
+++ evbuffer.c  Fri Feb 17 17:40:53 2006
@@ -92,13 +92,21 @@
        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 we have a high watermark configured then we don't want to
+        * read more data than would make us reach the watermark.
+        */
+       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;
@@ -124,7 +132,8 @@
 
                /* Now schedule a callback for us */
                evbuffer_setcb(buf, bufferevent_read_pressure_cb, bufev);
-               return;
+
+               /* Fallthrough to allow the user callback to run */
        }
 
        /* Invoke the user callback - must always be called last */
--- buffer.c.orig       Thu Jun  9 14:35:48 2005
+++ buffer.c    Fri Feb 17 17:40:06 2006
@@ -332,8 +332,21 @@
 #endif
 
 #ifdef FIONREAD
-       if (ioctl(fd, FIONREAD, &n) == -1 || n == 0)
+       if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) {
                n = EVBUFFER_MAX_READ;
+       } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
+               /*
+                * It's possible that a lot of data is available for
+                * reading.  We do not want to exhaust resources
+                * before the reader has a chance to do something
+                * about it.  If the reader does not tell us how much
+                * data we should read, we artifically limit it.
+                */
+               if (n > buf->totallen << 2)
+                       n = buf->totallen << 2;
+               if (n < EVBUFFER_MAX_READ)
+                       n = EVBUFFER_MAX_READ;
+       }
 #endif 
        if (howmuch < 0 || howmuch > n)
                howmuch = n;
_______________________________________________
Libevent-users mailing list
[email protected]
http://monkey.org/mailman/listinfo/libevent-users

Reply via email to