]> granicus.if.org Git - libevent/commitdiff
limit the amount of data bufferevents are going to consume to something
authorNiels Provos <provos@gmail.com>
Mon, 13 Feb 2006 01:51:58 +0000 (01:51 +0000)
committerNiels Provos <provos@gmail.com>
Mon, 13 Feb 2006 01:51:58 +0000 (01:51 +0000)
reasonable; in some circumstances it could happen that libevent happily
allocated 100MB in read buffers without telling the user; found by
christopher maxwell - parts of these changes are from his patch.

svn:r200

buffer.c
evbuffer.c

index 7ce5bef1ab3c7585c7cfa5336cd780521135ca82..e3c0ef9a52f2cb3ba8e94eb24f95c1f6e04b8b1c 100644 (file)
--- a/buffer.c
+++ b/buffer.c
@@ -340,8 +340,21 @@ evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
 #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;
index 0e7ef00cd70522c366d002e41fbb9e3f077ea1c7..7bd8d49a3da661d3be3a02dda3d6461f5bdc3e00 100644 (file)
@@ -92,13 +92,21 @@ bufferevent_readcb(int fd, short event, void *arg)
        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;